/// <summary> /// Signal that we've received a ping from a neighbor /// </summary> /// <param name="region"></param> private void HandleNeighborPing(SimpleRegionInfo region) { bool newNeighbor = false; KnownNeighborRegion neighbor; lock (_knownNeighbors) { if (_knownNeighbors.TryGetValue(region.RegionHandle, out neighbor)) { neighbor.LastPingReceivedOn = Util.GetLongTickCount(); } else { newNeighbor = true; neighbor = new KnownNeighborRegion { LastPingReceivedOn = Util.GetLongTickCount(), RegionInfo = region }; _knownNeighbors.Add(neighbor.RegionInfo.RegionHandle, neighbor); } } if (newNeighbor) { TriggerNeighborStateChange(region, NeighborStateChangeType.NeighborUp); } TriggerNeighborStateChange(region, NeighborStateChangeType.NeighborPing); }
// Called with _knownNeighbors already locked. // Returns true if anything added to visibleNeighbors private void AddVisibleRegion(SimpleRegionInfo[,] visibleNeighbors, bool[,] inspected, uint x, uint y, uint xmin, uint xmax, uint ymin, uint ymax) { if ((x < xmin) || (x > xmax) || (y < ymin) || (y > ymax)) { return; // off the grid, nothing to do } // visibleNeighbors[] and inspected[] arrays use 0-based coordinates. uint xmap = x - xmin; uint ymap = y - ymin; if (inspected[xmap, ymap]) { return; // already did this one } inspected[xmap, ymap] = true; SimpleRegionInfo neighbor = FindKnownNeighbor(x, y); if (neighbor == null) { return; // region not present } visibleNeighbors[xmap, ymap] = neighbor; AddVisibleNeighbors(visibleNeighbors, inspected, x, y, xmin, xmax, ymin, ymax); }
/// <summary> /// Drops the given presence /// </summary> /// <param name="neighbor">The presence to drop</param> /// <param name="onlyIfFar">Only drop if the presence is a far presence</param> private async Task DropRemotePresence(SimpleRegionInfo neighbor, bool onlyIfFar) { AvatarRemotePresence foundPresence = null; TryGetRemotePresenceLocked(neighbor.RegionHandle, (AvatarRemotePresence presence) => { foundPresence = presence; if (presence != null) { if (onlyIfFar && !presence.IsFarPresence) { return; } //You can not send a disablesimulator for the remote region //the viewer processes all disablesimulator messages coming from this //region as a disablesimulator message FOR this region //therefore, we remove the neighbor from our known regions list //and ask the sim on the other end to tear down the connection _remotePresences.Remove(neighbor.RegionHandle); } }); if (foundPresence != null) { //send a close to the neighbor var intercom = _scene.InterregionComms; if (intercom != null) { await intercom.SendCloseAgentAsync(neighbor, _sp.UUID); } } }
private async Task <bool> WaitForScenePresenceEstablished(SimpleRegionInfo region) { //this is the HTTP timeout, however the actual wait timeout on the receiving side is 10 seconds //so that timeout should be triggered first const int HTTP_SP_WAIT_TIMEOUT = 15000; var req = (HttpWebRequest)HttpWebRequest.Create(region.InsecurePublicHTTPServerURI + String.Format("/agent2/{0}/{1}", _sp.UUID, region.RegionHandle)); req.Headers["authorization"] = Util.GenerateHttpAuthorization(_scene.GridSendKey); req.Timeout = HTTP_SP_WAIT_TIMEOUT; req.ReadWriteTimeout = HTTP_SP_WAIT_TIMEOUT; req.Method = "GET"; try { using (WebResponse response = await req.GetResponseAsync(HTTP_SP_WAIT_TIMEOUT)) { //we do nothing besides dispose on success. a 200 response means all is well } return(true); } catch (Exception e) { _log.ErrorFormat("[REMOTEPRESENCE]: Waiting for viewer connection from {0} to {1} failed: {2}", _sp.Name, region.RegionHandle, e); return(false); } }
// see IGridServices public List <SimpleRegionInfo> RequestNeighbours(uint x, uint y) { Hashtable respData = MapBlockQuery((int)x - 1, (int)y - 1, (int)x + 1, (int)y + 1); List <SimpleRegionInfo> neighbours = new List <SimpleRegionInfo>(); foreach (ArrayList neighboursList in respData.Values) { foreach (Hashtable neighbourData in neighboursList) { uint regX = Convert.ToUInt32(neighbourData["x"]); uint regY = Convert.ToUInt32(neighbourData["y"]); if ((x != regX) || (y != regY)) { string simIp = (string)neighbourData["sim_ip"]; uint port = Convert.ToUInt32(neighbourData["sim_port"]); // string externalUri = (string) neighbourData["sim_uri"]; // string externalIpStr = String.Empty; try { // externalIpStr = Util.GetHostFromDNS(simIp).ToString(); Util.GetHostFromDNS(simIp).ToString(); } catch (SocketException e) { m_log.WarnFormat( "[OGS1 GRID SERVICES]: RequestNeighbours(): Lookup of neighbour {0} failed! Not including in neighbours list. {1}", simIp, e); continue; } SimpleRegionInfo sri = new SimpleRegionInfo(regX, regY, simIp, port); sri.RemotingPort = Convert.ToUInt32(neighbourData["remoting_port"]); if (neighbourData.ContainsKey("http_port")) { sri.HttpPort = Convert.ToUInt32(neighbourData["http_port"]); } else { m_log.Error("[OGS1 GRID SERVICES]: Couldn't find httpPort, using default 9000; please upgrade your grid-server to r7621 or later"); sri.HttpPort = 9000; // that's the default and will probably be wrong } sri.RegionID = new UUID((string)neighbourData["uuid"]); neighbours.Add(sri); } } } return(neighbours); }
/// <summary> /// Signal that a neighbor has gone down /// </summary> /// <param name="region"></param> private void HandleNeighborDown(SimpleRegionInfo region) { lock (_knownNeighbors) { _knownNeighbors.Remove(region.RegionHandle); } TriggerNeighborStateChange(region, NeighborStateChangeType.NeighborDown); }
public async Task <Tuple <bool, string> > SendCreateRemoteChildAgentAsync(SimpleRegionInfo regionInfo, AgentCircuitData aCircuit) { if (regionInfo == null) { throw new ArgumentNullException("regionInfo cannot be null"); } return(await m_regionClient.DoCreateChildAgentCallAsync(regionInfo, aCircuit)); }
private void EventManager_OnAvatarLeavingRegion(ScenePresence presence, SimpleRegionInfo newRegion) { //Add them to the cache LeavingRegionInfo info = new LeavingRegionInfo() { RegionServerURI = newRegion.InsecurePublicHTTPServerURI, SessionID = presence.ControllingClient.SessionId }; _avatarRegionCache.AddOrUpdate(presence.UUID, info, CACHE_EXPIRATION_TIME); }
void srm_OnNeighborStateChange(SimpleRegionInfo neighbor, NeighborStateChangeType changeType) { if (stateChangeCounts.ContainsKey(changeType)) { stateChangeCounts[changeType]++; } else { stateChangeCounts[changeType] = 1; } }
/// <summary> /// Drops the given presence taking the operation semaphore /// </summary> /// <param name="neighbor">The presence to drop</param> /// <param name="onlyIfFar">Only drop if the presence is a far presence</param> public async Task DropRemotePresenceLocked(SimpleRegionInfo neighbor, bool onlyIfFar) { try { await _operationSemaphore.WaitAsync(); await DropRemotePresence(neighbor, onlyIfFar); } finally { _operationSemaphore.Release(); } }
public ChildAgentUpdate2Response SendChildAgentUpdate2(SimpleRegionInfo regionInfo, AgentData data) { foreach (Scene s in m_sceneList) { if (s.RegionInfo.RegionHandle == regionInfo.RegionHandle) { return(s.IncomingChildAgentDataUpdate2(data)); } } return(ChildAgentUpdate2Response.Error); }
/// <summary> /// Returns a list of neighbors we are aware of that are within the given client draw distance from any /// of our edges /// </summary> /// <param name="drawDistance">DD in meters</param> /// <returns>List of known neighbors</returns> public List <SimpleRegionInfo> GetKnownNeighborsWithinClientDD(uint drawDistance, uint maxRange) { drawDistance = Math.Max(drawDistance, 64); drawDistance = Math.Min(drawDistance, MAX_DRAW_DISTANCE); uint xmin, xmax, ymin, ymax; var regionInfo = _scene.RegionInfo; Util.GetDrawDistanceBasedRegionRectangle(drawDistance, maxRange, regionInfo.RegionLocX, regionInfo.RegionLocY, out xmin, out xmax, out ymin, out ymax); uint gridsize = xmax - xmin + 1; uint center = (xmax - xmin) / 2; List <SimpleRegionInfo> neighbors = new List <SimpleRegionInfo>(); // visibleNeighbors[] and inspected[] arrays use 0-based coordinates. SimpleRegionInfo[,] visibleNeighbors = new SimpleRegionInfo[gridsize, gridsize]; lock (_knownNeighbors) { foreach (KnownNeighborRegion neighbor in _knownNeighbors.Values) { if (Util.IsWithinDDRectangle(neighbor.RegionInfo.RegionLocX, neighbor.RegionInfo.RegionLocY, xmin, xmax, ymin, ymax)) { //region within bounds neighbors.Add(neighbor.RegionInfo); } } // Apply per-presence region visibility filter bool[,] inspected = new bool[gridsize, gridsize]; // context for recursive call // The starting/center point in the visibility grid is always included. visibleNeighbors[center, center] = new SimpleRegionInfo(regionInfo); inspected[center, center] = true; // Recursively path-find all visible neighbors. AddVisibleNeighbors(visibleNeighbors, inspected, regionInfo.RegionLocX, regionInfo.RegionLocY, xmin, xmax, ymin, ymax); } // Now replace the full list of neighbors with the regions in the filtered visible array. neighbors.Clear(); foreach (var region in visibleNeighbors) { if ((region != null) && (region.RegionHandle != regionInfo.RegionHandle)) // got one and it's not this one { neighbors.Add(region); } } return(neighbors); }
/// <summary> /// Called by the surrounding region manager when there is a region state change /// </summary> /// <param name="neighbor"></param> /// <param name="changeType"></param> void SurroundingRegions_OnNeighborStateChange(SimpleRegionInfo neighbor, NeighborStateChangeType changeType) { switch (changeType) { case NeighborStateChangeType.NeighborUp: this.HandleNeighborUp(neighbor); break; case NeighborStateChangeType.NeighborDown: this.HandleNeighborDown(neighbor); break; } }
public bool HasEstablishedConnection(SimpleRegionInfo region) { AvatarRemotePresence pres; lock (_remotePresences) { if (_remotePresences.TryGetValue(region.RegionHandle, out pres)) { return(pres.State == RemotePresenceState.Established); } } return(false); }
/// <summary> /// Signal that a neighbor has come up /// </summary> /// <param name="region">The region information</param> private void HandleNeighborUp(SimpleRegionInfo region) { var newNeighbor = new KnownNeighborRegion { LastPingReceivedOn = Util.GetLongTickCount(), RegionInfo = region }; lock (_knownNeighbors) { _knownNeighbors[region.RegionHandle] = newNeighbor; } TriggerNeighborStateChange(region, NeighborStateChangeType.NeighborUp); }
/// <summary> /// Triggers the state change event /// </summary> /// <param name="neighbor"></param> /// <param name="neighborStateChangeType"></param> private void TriggerNeighborStateChange(SimpleRegionInfo neighbor, NeighborStateChangeType neighborStateChangeType) { if (neighborStateChangeType != NeighborStateChangeType.NeighborPing) { _log.InfoFormat("[REGIONMANAGER]: Neighbor region {0} at {1} state change {2}", neighbor.RegionHandle, Util.RegionHandleToLocationString(neighbor.RegionHandle), neighborStateChangeType); } var stateChangeHandler = this.OnNeighborStateChange; if (stateChangeHandler != null) { stateChangeHandler(neighbor, neighborStateChangeType); } }
public async Task <bool> DoCloseAgentCallAsync(SimpleRegionInfo region, UUID id) { string uri = region.InsecurePublicHTTPServerURI + "/agent/" + id + "/" + region.RegionHandle.ToString() + "/"; HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri); request.Method = "DELETE"; request.Timeout = AGENT_UPDATE_TIMEOUT; request.ReadWriteTimeout = AGENT_UPDATE_TIMEOUT; request.Headers["authorization"] = GenerateAuthorization(); try { WebResponse webResponse = await request.GetResponseAsync(AGENT_UPDATE_TIMEOUT); if (webResponse == null) { m_log.Info("[REST COMMS]: Null reply on agent delete "); return(false); } StreamReader sr = new StreamReader(webResponse.GetResponseStream()); string response = await sr.ReadToEndAsync(); response.Trim(); sr.Close(); return(true); } catch (WebException ex) { m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex); } catch (Exception ex) { m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex); } return(false); }
public ChildAgentUpdate2Response SendChildAgentUpdate2(SimpleRegionInfo regionInfo, AgentData data) { int childAgentUpdateStart = Environment.TickCount; try { // Try local first if (m_localBackend.SendChildAgentUpdate2(regionInfo, data) == ChildAgentUpdate2Response.Ok) { return(ChildAgentUpdate2Response.Ok); } // else do the remote thing if (!m_localBackend.IsLocalRegion(regionInfo.RegionHandle)) { RegionClient.AgentUpdate2Ret ret = m_regionClient.DoChildAgentUpdateCall2(regionInfo, data); switch (ret) { case RegionClient.AgentUpdate2Ret.Ok: return(ChildAgentUpdate2Response.Ok); case RegionClient.AgentUpdate2Ret.Error: return(ChildAgentUpdate2Response.Error); case RegionClient.AgentUpdate2Ret.NotFound: return(ChildAgentUpdate2Response.MethodNotAvailalble); case RegionClient.AgentUpdate2Ret.AccessDenied: return(ChildAgentUpdate2Response.AccessDenied); } } return(ChildAgentUpdate2Response.Error); } finally { m_log.DebugFormat("[REST COMM] SendChildAgentUpdateCall2: {0} ms", Environment.TickCount - childAgentUpdateStart); } }
private static List <SimpleRegionInfo> ExtractRegionInfoFromMapBlockQuery(uint x, uint y, Hashtable respData) { List <SimpleRegionInfo> neighbours = new List <SimpleRegionInfo>(); foreach (ArrayList neighboursList in respData.Values) { foreach (Hashtable neighbourData in neighboursList) { uint regX = Convert.ToUInt32(neighbourData["x"]); uint regY = Convert.ToUInt32(neighbourData["y"]); if ((x != regX) || (y != regY)) { string simIp = (string)neighbourData["sim_ip"]; uint port = Convert.ToUInt32(neighbourData["sim_port"]); SimpleRegionInfo sri = new SimpleRegionInfo(regX, regY, simIp, port); sri.RegionID = new UUID((string)neighbourData["uuid"]); sri.RemotingPort = Convert.ToUInt32(neighbourData["remoting_port"]); if (neighbourData.ContainsKey("http_port")) { sri.HttpPort = Convert.ToUInt32(neighbourData["http_port"]); } if (neighbourData.ContainsKey("outside_ip")) { sri.OutsideIP = (string)neighbourData["outside_ip"]; } neighbours.Add(sri); } } } return(neighbours); }
private ChildAgentUpdate2Response SendChildAgentUpdate2() { ScenePresence agent = _avatar.ScenePresence; SceneObjectGroup sceneObjectGroup = _avatar.TransitArgs.RideOnGroup; SceneObjectPart part = _avatar.TransitArgs.RideOnPart; ulong newRegionHandle = _avatar.TransitArgs.DestinationRegion.RegionHandle; SimpleRegionInfo neighbourRegion = _avatar.TransitArgs.DestinationRegion; Vector3 pos = _avatar.TransitArgs.LocationInDestination; AgentLocomotionFlags locomotionFlags = 0; if (_avatar.TransitArgs.Type == TransitType.OutboundCrossing) { locomotionFlags = AgentLocomotionFlags.Crossing; } else if (_avatar.TransitArgs.Type == TransitType.OutboundTeleport) { locomotionFlags = AgentLocomotionFlags.Teleport; } AgentData cAgent = new AgentData(); agent.CopyToForRootAgent(cAgent); if (part == null) { cAgent.Position = pos; } cAgent.LocomotionState = 1; cAgent.LocomotionFlags = locomotionFlags; List <SceneObjectGroup> attachments = agent.CollectAttachmentsForCrossing(); //try the new comms first var engine = ProviderRegistry.Instance.Get <ISerializationEngine>(); if (engine == null) { _log.ErrorFormat("[SCENE COMM]: Cannot send child agent update to {0}, Serialization engine is missing!", neighbourRegion.RegionHandle); return(ChildAgentUpdate2Response.Error); } List <byte[]> serializedAttachments = new List <byte[]>(); foreach (var att in attachments) { //mark the SOG in-transit. this along with the serialization below sends a disable to the script engine, but they are not cumulative att.StartTransit(); //we are stopping the scripts as part of the serialization process here //this means that later on, should the remote creation call fail, we need to re-enable them //reenabling is done via EndTransit with success==false byte[] sogBytes = engine.SceneObjectSerializer.SerializeGroupToBytes(att, SerializationFlags.FromCrossing | SerializationFlags.StopScripts | SerializationFlags.SerializeScriptBytecode); serializedAttachments.Add(sogBytes); } cAgent.SerializedAttachments = serializedAttachments; var scene = agent.Scene; cAgent.CallbackURI = scene.RegionInfo.InsecurePublicHTTPServerURI + "/agent/" + agent.UUID.ToString() + "/" + agent.Scene.RegionInfo.RegionHandle.ToString() + "/release/"; ChildAgentUpdate2Response resp = scene.InterregionComms.SendChildAgentUpdate2(neighbourRegion, cAgent); if (resp == ChildAgentUpdate2Response.Error) { _log.ErrorFormat("[SCENE COMM]: Error sending child agent update to {0}", neighbourRegion.RegionHandle); } else if (resp == ChildAgentUpdate2Response.MethodNotAvailalble) { _log.ErrorFormat("[SCENE COMM]: Error sending child agent update to {0}, ChildAgentUpdate2 not available. Falling back to old method", neighbourRegion.RegionHandle); } return(resp); }
public AgentUpdate2Ret DoChildAgentUpdateCall2(SimpleRegionInfo regInfo, AgentData data) { ulong regionHandle = GetRegionHandle(regInfo.RegionHandle); string uri = "http://" + regInfo.ExternalHostName + ":" + regInfo.HttpPort + "/agent2/" + data.AgentID + "/" + regionHandle + "/"; HttpWebRequest agentPutRequest = (HttpWebRequest)WebRequest.Create(uri); agentPutRequest.Method = "PUT"; agentPutRequest.ContentType = "application/octet-stream"; agentPutRequest.Timeout = AGENT_UPDATE_TIMEOUT; agentPutRequest.Headers["authorization"] = GenerateAuthorization(); AgentPutMessage message = AgentPutMessage.FromAgentData(data); try { // send the Post Stream os = agentPutRequest.GetRequestStream(); ProtoBuf.Serializer.Serialize(os, message); os.Flush(); os.Close(); m_log.InfoFormat("[REST COMMS]: PUT DoChildAgentUpdateCall2 request to remote sim {0}", uri); } catch (Exception e) { m_log.ErrorFormat("[REST COMMS]: DoChildAgentUpdateCall2 call failed {0}", e); return(AgentUpdate2Ret.Error); } // Let's wait for the response //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall"); try { HttpWebResponse webResponse = (HttpWebResponse)agentPutRequest.GetResponse(); if (webResponse == null) { m_log.Error("[REST COMMS]: Null reply on DoChildAgentUpdateCall2 put"); return(AgentUpdate2Ret.Error); } StreamReader sr = new StreamReader(webResponse.GetResponseStream()); string reply = sr.ReadToEnd().Trim(); sr.Close(); //this will happen during the initial rollout and tells us we need to fall back to the //old method if (webResponse.StatusCode == HttpStatusCode.NotFound) { m_log.InfoFormat("[REST COMMS]: NotFound on reply of DoChildAgentUpdateCall2"); return(AgentUpdate2Ret.NotFound); } else if (webResponse.StatusCode == HttpStatusCode.OK) { return(AgentUpdate2Ret.Ok); } else { m_log.ErrorFormat("[REST COMMS]: Error on reply of DoChildAgentUpdateCall2 {0}", reply); return(AgentUpdate2Ret.Error); } } catch (WebException ex) { HttpWebResponse webResponse = ex.Response as HttpWebResponse; if (webResponse != null) { //this will happen during the initial rollout and tells us we need to fall back to the //old method if (webResponse.StatusCode == HttpStatusCode.NotFound) { m_log.InfoFormat("[REST COMMS]: NotFound on reply of DoChildAgentUpdateCall2"); return(AgentUpdate2Ret.NotFound); } if (webResponse.StatusCode == HttpStatusCode.Forbidden) { m_log.InfoFormat("[REST COMMS]: Forbidden returned on reply of DoChildAgentUpdateCall2"); return(AgentUpdate2Ret.AccessDenied); } } m_log.ErrorFormat("[REST COMMS]: exception on reply of DoChildAgentUpdateCall2 {0} Sz {1}", ex, agentPutRequest.ContentLength); } return(AgentUpdate2Ret.Error); }
public async Task <Tuple <bool, string> > DoCreateChildAgentCallAsync(SimpleRegionInfo regionInfo, AgentCircuitData aCircuit) { string uri = regionInfo.InsecurePublicHTTPServerURI + "/agent/" + aCircuit.AgentID + "/"; HttpWebRequest agentCreateRequest = (HttpWebRequest)HttpWebRequest.Create(uri); agentCreateRequest.Method = "POST"; agentCreateRequest.ContentType = "application/json"; agentCreateRequest.Timeout = AGENT_UPDATE_TIMEOUT; agentCreateRequest.ReadWriteTimeout = AGENT_UPDATE_TIMEOUT; agentCreateRequest.Headers["authorization"] = GenerateAuthorization(); OSDMap args = null; try { args = aCircuit.PackAgentCircuitData(); } catch (Exception e) { m_log.Debug("[REST COMMS]: PackAgentCircuitData failed with exception: " + e.Message); return(Tuple.Create(false, "PackAgentCircuitData exception")); } // Add the regionhandle of the destination region ulong regionHandle = GetRegionHandle(regionInfo.RegionHandle); args["destination_handle"] = OSD.FromString(regionHandle.ToString()); string strBuffer = String.Empty; byte[] buffer = new byte[1]; try { strBuffer = OSDParser.SerializeJsonString(args); UTF8Encoding str = new UTF8Encoding(); buffer = str.GetBytes(strBuffer); } catch (Exception e) { m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of ChildCreate: {0}", e.Message); return(Tuple.Create(false, "Exception thrown on serialization of ChildCreate")); } try { // send the Post agentCreateRequest.ContentLength = buffer.Length; //Count bytes to send Stream os = await agentCreateRequest.GetRequestStreamAsync(); await os.WriteAsync(buffer, 0, strBuffer.Length); //Send it await os.FlushAsync(); os.Close(); //m_log.InfoFormat("[REST COMMS]: Posted CreateChildAgent request to remote sim {0}", uri); } catch (Exception e) { m_log.WarnFormat("[REST COMMS]: Unable to contact remote region {0}: {1}", regionInfo.RegionHandle, e.Message); return(Tuple.Create(false, "cannot contact remote region")); } // Let's wait for the response //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall"); try { WebResponse webResponse = await agentCreateRequest.GetResponseAsync(AGENT_UPDATE_TIMEOUT); if (webResponse == null) { m_log.Warn("[REST COMMS]: Null reply on DoCreateChildAgentCall post"); return(Tuple.Create(false, "response from remote region was null")); } StreamReader sr = new StreamReader(webResponse.GetResponseStream()); string response = await sr.ReadToEndAsync(); response.Trim(); sr.Close(); //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", response); if (String.IsNullOrEmpty(response)) { m_log.Info("[REST COMMS]: Empty response on DoCreateChildAgentCall post"); return(Tuple.Create(false, "response from remote region was empty")); } try { // we assume we got an OSDMap back OSDMap r = GetOSDMap(response); bool success = r["success"].AsBoolean(); string reason = r["reason"].AsString(); return(Tuple.Create(success, reason)); } catch (NullReferenceException e) { m_log.WarnFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", e.Message); // check for old style response if (response.ToLower().StartsWith("true")) { return(Tuple.Create(true, String.Empty)); } return(Tuple.Create(false, "exception on reply of DoCreateChildAgentCall")); } } catch (WebException ex) { m_log.WarnFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex); return(Tuple.Create(false, "web exception")); } catch (Exception ex) { m_log.WarnFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex); return(Tuple.Create(false, "web exception")); } }
public async Task <bool> SendCloseAgentAsync(SimpleRegionInfo regionInfo, UUID id) { return(await m_regionClient.DoCloseAgentCallAsync(regionInfo, id)); }
public AgentUpdate2Ret DoChildAgentUpdateCall2(SimpleRegionInfo regInfo, AgentData data) { ulong regionHandle = GetRegionHandle(regInfo.RegionHandle); string uri = "http://" + regInfo.ExternalHostName + ":" + regInfo.HttpPort + "/agent2/" + data.AgentID + "/" + regionHandle + "/"; HttpWebRequest agentPutRequest = (HttpWebRequest)WebRequest.Create(uri); agentPutRequest.Method = "PUT"; agentPutRequest.ContentType = "application/octet-stream"; agentPutRequest.Timeout = AGENT_UPDATE_TIMEOUT; agentPutRequest.Headers["authorization"] = GenerateAuthorization(); AgentPutMessage message = AgentPutMessage.FromAgentData(data); try { // send the Post Stream os = agentPutRequest.GetRequestStream(); ProtoBuf.Serializer.Serialize(os, message); os.Flush(); os.Close(); m_log.InfoFormat("[REST COMMS]: PUT DoChildAgentUpdateCall2 request to remote sim {0}", uri); } catch (Exception e) { m_log.ErrorFormat("[REST COMMS]: DoChildAgentUpdateCall2 call failed {0}", e); return AgentUpdate2Ret.Error; } // Let's wait for the response //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall"); try { HttpWebResponse webResponse = (HttpWebResponse)agentPutRequest.GetResponse(); if (webResponse == null) { m_log.Error("[REST COMMS]: Null reply on DoChildAgentUpdateCall2 put"); return AgentUpdate2Ret.Error; } StreamReader sr = new StreamReader(webResponse.GetResponseStream()); string reply = sr.ReadToEnd().Trim(); sr.Close(); //this will happen during the initial rollout and tells us we need to fall back to the //old method if (webResponse.StatusCode == HttpStatusCode.NotFound) { m_log.InfoFormat("[REST COMMS]: NotFound on reply of DoChildAgentUpdateCall2"); return AgentUpdate2Ret.NotFound; } else if (webResponse.StatusCode == HttpStatusCode.OK) { return AgentUpdate2Ret.Ok; } else { m_log.ErrorFormat("[REST COMMS]: Error on reply of DoChildAgentUpdateCall2 {0}", reply); return AgentUpdate2Ret.Error; } } catch (WebException ex) { HttpWebResponse webResponse = ex.Response as HttpWebResponse; if (webResponse != null) { //this will happen during the initial rollout and tells us we need to fall back to the //old method if (webResponse.StatusCode == HttpStatusCode.NotFound) { m_log.InfoFormat("[REST COMMS]: NotFound on reply of DoChildAgentUpdateCall2"); return AgentUpdate2Ret.NotFound; } if (webResponse.StatusCode == HttpStatusCode.Forbidden) { m_log.InfoFormat("[REST COMMS]: Forbidden returned on reply of DoChildAgentUpdateCall2"); return AgentUpdate2Ret.AccessDenied; } } m_log.ErrorFormat("[REST COMMS]: exception on reply of DoChildAgentUpdateCall2 {0} Sz {1}", ex, agentPutRequest.ContentLength); } return AgentUpdate2Ret.Error; }
private async Task HandleNeighborUp(SimpleRegionInfo neighbor) { // on any neighbor change, we need to recalculate all neighbors because // visibility rules may have resulted in more than one new neighbor. await CalculateAndResyncNeighbors((uint)_sp.DrawDistance, _sp.ControllingClient.NeighborsRange, 0); }
/// <summary> /// Attempts to establish a presence on the given region. Does this while waiting for other major tasks to complete /// </summary> /// <param name="region">The region we want to establish a child presence on</param> /// <param name="forceReestablish">Whether to force a reestablishment even if we already think we have a remote presence</param> /// <param name="isFarPresence">Is this presence intentionally far away? Eg. The beginning of a remote teleport</param> /// <returns></returns> public async Task <Tuple <EstablishPresenceResult, string> > EstablishPresenceOnRegionLocked(SimpleRegionInfo region, bool forceReestablish, bool isFarPresence) { try { await _operationSemaphore.WaitAsync(); return(await this.EstablishPresenceOnRegion(region, forceReestablish, isFarPresence)); } finally { _operationSemaphore.Release(); } }
/// <summary> /// Attempts to establish a presence on the given region /// </summary> /// <param name="region">The region we want to establish a child presence on</param> /// <param name="forceReestablish">Whether to force a reestablishment even if we already think we have a remote presence</param> /// <param name="isFarPresence">Is this presence intentionally far away? Eg. The beginning of a remote teleport</param> /// <returns></returns> private async Task <Tuple <EstablishPresenceResult, string> > EstablishPresenceOnRegion(SimpleRegionInfo region, bool forceReestablish, bool isFarPresence) { Task <Tuple <EstablishPresenceResult, string> > establishTask = null; bool presenceExisted = false; //check if we already have or are waiting on an establish TryGetRemotePresenceLocked(region.RegionHandle, (AvatarRemotePresence presence) => { if (presence != null && !forceReestablish) { //we have a presence //if it is established just return if (presence.State == RemotePresenceState.Established) { presenceExisted = true; } else { //if not, we can await the existing callback establishTask = presence.EstablishTask; } } else { //we have no presence and we're not waiting for a callback //begin an async establish and await a callback presence = new AvatarRemotePresence { PresenceInfo = new RemotePresenceInfo { RegionInfo = region, CapsPath = CapsUtil.GetRandomCapsObjectPath() }, IsFarPresence = isFarPresence, State = RemotePresenceState.Establishing }; if (_remotePresences.ContainsKey(region.RegionHandle)) { _remotePresences.Remove(region.RegionHandle); } _remotePresences.Add(region.RegionHandle, presence); establishTask = DoEstablishPresenceOnRegion(region, presence); presence.EstablishTask = establishTask; } }); //nothing to do, we're already established if (presenceExisted) { return(Tuple.Create(EstablishPresenceResult.Success, String.Empty)); } return(await establishTask); }
private async Task <Tuple <EstablishPresenceResult, string> > DoEstablishPresenceOnRegion(SimpleRegionInfo region, AvatarRemotePresence initPresence) { Tuple <EstablishPresenceResult, string> establishResult; try { establishResult = await this.LaunchNewEstablishChildTask(initPresence, region); } catch (Exception e) { establishResult = new Tuple <EstablishPresenceResult, string>(EstablishPresenceResult.ErrorInformingRegion, e.Message); } bool failure = false; TryGetRemotePresenceLocked(region.RegionHandle, (AvatarRemotePresence presence) => { //success, change the status of the task if (presence != null) { if (establishResult.Item1 == EstablishPresenceResult.Success) { presence.State = RemotePresenceState.ViewerWait; } else { //failure contacting other region _remotePresences.Remove(region.RegionHandle); failure = true; } } else { string context = (_sp == null) ? String.Empty : " for " + _sp.Name; failure = true; //hmm, someone stole this presence from us _log.ErrorFormat("[REMOTEPRESENCE]: Unable to update child presence established to {0}{1}. Child presence missing.", establishResult, context); establishResult = Tuple.Create(EstablishPresenceResult.ConnectionAborted, "Connection was aborted"); } }); if (failure) { return(establishResult); } //now we need to call out to the remote region to wait for the SP to be set up bool waitSuccess = await WaitForScenePresenceEstablished(region); Tuple <EstablishPresenceResult, string> result = null; TryGetRemotePresenceLocked(region.RegionHandle, (AvatarRemotePresence presence) => { //success, change the status of the task if (presence != null) { if (waitSuccess) { presence.State = RemotePresenceState.Established; result = Tuple.Create(EstablishPresenceResult.Success, String.Empty); } else { //failure waiting for SP _remotePresences.Remove(region.RegionHandle); result = Tuple.Create(EstablishPresenceResult.ClientWaitTimeout, "Destination region never received a connection from the viewer"); } } else { //hmm, someone stole this presence from us _log.ErrorFormat("[REMOTEPRESENCE]: Unable to update child presence established to {0} for {1}. Child presence missing.", establishResult, _sp.Name); result = Tuple.Create(EstablishPresenceResult.ConnectionAborted, "Connection was aborted"); } }); return(result); }
public override async Task StateEntry() { await _avatar.TriggerOnTransitStageChanged(TransitStage.SendEstablishChildPresence, _avatar.RideOnPrims); SimpleRegionInfo destination = _avatar.TransitArgs.DestinationRegion; //do we have a presence on the destination? if (!_avatar.ScenePresence.RemotePresences.HasPresenceOnRegion(destination.RegionHandle)) { //no, we need to establish a new presence Tuple <EstablishPresenceResult, string> result = await _avatar.ScenePresence.RemotePresences.EstablishPresenceOnRegionLocked(destination, false, true); if (result.Item1 != EstablishPresenceResult.Success) { //something broke _avatar.ScenePresence.ControllingClient.SendAlertMessage( "Unable to complete transfer to new region: " + result.Item2); throw new SendAvatarException( String.Format("Could not establish presence on remote region: {0}", result.Item2)); } RollbackActions.Push(() => { _avatar.ScenePresence.RemotePresences.DropRemotePresenceLocked(destination, true).Wait(); }); } AvatarRemotePresence remotePresence = null; _avatar.ScenePresence.RemotePresences.TryGetRemotePresenceLocked(destination.RegionHandle, (AvatarRemotePresence pres) => { remotePresence = pres; } ); if (remotePresence == null) { //something is horked throw new SendAvatarException( String.Format("Presence could not be established on new region for {0}", _avatar.ScenePresence.Name)); } //we have a presence now, we can send the child agent update await _avatar.TriggerOnTransitStageChanged(TransitStage.SendAvatarHandoff, _avatar.RideOnPrims); //the ChildAgentUpdate below will always stop attachment scripts to transmit their state //if anything from this point on fails, we need to start the scripts running again RollbackActions.Push(() => { List <SceneObjectGroup> attachments = _avatar.ScenePresence.GetAttachments(); foreach (var att in attachments) { att.EndTransit(false); } } ); // Invoke the agent2 entry point ChildAgentUpdate2Response rc = this.SendChildAgentUpdate2(); switch (rc) { case ChildAgentUpdate2Response.Ok: break; // continue normally case ChildAgentUpdate2Response.AccessDenied: throw new SendAvatarException( String.Format("Region entry denied for {0}", _avatar.ScenePresence.Name)); case ChildAgentUpdate2Response.MethodNotAvailalble: throw new SendAvatarException( String.Format("Region change not available for {0}", _avatar.ScenePresence.Name)); case ChildAgentUpdate2Response.Error: default: throw new SendAvatarException( String.Format("Region change failed for {0}", _avatar.ScenePresence.Name)); } //this avatar is now considered a child agent _avatar.ScenePresence.MakeChildAgent(_avatar.TransitArgs.DestinationRegion.RegionHandle); //if there is a failure, we will need to restore the user as a root agent Vector3 restorePos = _avatar.ScenePresence.AbsolutePosition; Util.ForceValidRegionXY(ref restorePos); RollbackActions.Push(() => { _avatar.ScenePresence.MakeRootAgent(restorePos); }); //the user is ready to be transfered IEventQueue eq = _avatar.ScenePresence.Scene.RequestModuleInterface <IEventQueue>(); bool eventWasQueued = false; switch (_avatar.TransitArgs.Type) { case TransitType.OutboundCrossing: eventWasQueued = eq.CrossRegion(_avatar.TransitArgs.DestinationRegion.RegionHandle, _avatar.TransitArgs.LocationInDestination, _avatar.ScenePresence.Velocity, _avatar.TransitArgs.DestinationRegion.ExternalEndPoint, remotePresence.PresenceInfo.FullCapsSeedURL, _avatar.ScenePresence.UUID, _avatar.ScenePresence.ControllingClient.SessionId); break; case TransitType.OutboundTeleport: eventWasQueued = eq.TeleportFinishEvent(_avatar.TransitArgs.DestinationRegion.RegionHandle, 13, _avatar.TransitArgs.DestinationRegion.ExternalEndPoint, 4, (uint)_avatar.TransitArgs.TeleportFlags, remotePresence.PresenceInfo.FullCapsSeedURL, _avatar.ScenePresence.UUID); break; default: throw new SendAvatarException(String.Format("Invalid transit type {0} for sending avatar {1}", _avatar.TransitArgs.Type)); } if (!eventWasQueued) { throw new SendAvatarException(String.Format("Unable to enqueue transfer event for {0}", _avatar.ScenePresence.Name)); } //wait for confirmation of avatar on the other side await _avatar.WaitForRelease(); //matching endtransit for all attachments List <SceneObjectGroup> sentAttachments = _avatar.ScenePresence.GetAttachments(); foreach (var att in sentAttachments) { att.EndTransit(true); } _avatar.ScenePresence.AttachmentsCrossedToNewRegion(); //unsit the SP if appropriate if (_avatar.TransitArgs.RideOnPart != null) { _avatar.TransitArgs.RideOnPart.RemoveSeatedAvatar(_avatar.ScenePresence, false); } //this avatar is history. _avatar.ScenePresence.Reset(_avatar.TransitArgs.DestinationRegion); _avatar.ScenePresence.Scene.EventManager.TriggerAvatarLeavingRegion(_avatar.ScenePresence, _avatar.TransitArgs.DestinationRegion); }
public async Task<Tuple<bool, string>> DoCreateChildAgentCallAsync(SimpleRegionInfo regionInfo, AgentCircuitData aCircuit) { string uri = regionInfo.InsecurePublicHTTPServerURI + "/agent/" + aCircuit.AgentID + "/"; HttpWebRequest agentCreateRequest = (HttpWebRequest)HttpWebRequest.Create(uri); agentCreateRequest.Method = "POST"; agentCreateRequest.ContentType = "application/json"; agentCreateRequest.Timeout = AGENT_UPDATE_TIMEOUT; agentCreateRequest.ReadWriteTimeout = AGENT_UPDATE_TIMEOUT; agentCreateRequest.Headers["authorization"] = GenerateAuthorization(); OSDMap args = null; try { args = aCircuit.PackAgentCircuitData(); } catch (Exception e) { m_log.Debug("[REST COMMS]: PackAgentCircuitData failed with exception: " + e.Message); return Tuple.Create(false, "PackAgentCircuitData exception"); } // Add the regionhandle of the destination region ulong regionHandle = GetRegionHandle(regionInfo.RegionHandle); args["destination_handle"] = OSD.FromString(regionHandle.ToString()); string strBuffer = ""; byte[] buffer = new byte[1]; try { strBuffer = OSDParser.SerializeJsonString(args); UTF8Encoding str = new UTF8Encoding(); buffer = str.GetBytes(strBuffer); } catch (Exception e) { m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of ChildCreate: {0}", e.Message); return Tuple.Create(false, "Exception thrown on serialization of ChildCreate"); } try { // send the Post agentCreateRequest.ContentLength = buffer.Length; //Count bytes to send Stream os = await agentCreateRequest.GetRequestStreamAsync(); await os.WriteAsync(buffer, 0, strBuffer.Length); //Send it await os.FlushAsync(); os.Close(); //m_log.InfoFormat("[REST COMMS]: Posted CreateChildAgent request to remote sim {0}", uri); } catch (Exception e) { m_log.WarnFormat("[REST COMMS]: Unable to contact remote region {0}: {1}", regionInfo.RegionHandle, e.Message); return Tuple.Create(false, "cannot contact remote region"); } // Let's wait for the response //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall"); try { WebResponse webResponse = await agentCreateRequest.GetResponseAsync(AGENT_UPDATE_TIMEOUT); if (webResponse == null) { m_log.Warn("[REST COMMS]: Null reply on DoCreateChildAgentCall post"); return Tuple.Create(false, "response from remote region was null"); } StreamReader sr = new StreamReader(webResponse.GetResponseStream()); string response = await sr.ReadToEndAsync(); response.Trim(); sr.Close(); //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", response); if (String.IsNullOrEmpty(response)) { m_log.Info("[REST COMMS]: Empty response on DoCreateChildAgentCall post"); return Tuple.Create(false, "response from remote region was empty"); } try { // we assume we got an OSDMap back OSDMap r = GetOSDMap(response); bool success = r["success"].AsBoolean(); string reason = r["reason"].AsString(); return Tuple.Create(success, reason); } catch (NullReferenceException e) { m_log.WarnFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", e.Message); // check for old style response if (response.ToLower().StartsWith("true")) return Tuple.Create(true, ""); return Tuple.Create(false, "exception on reply of DoCreateChildAgentCall"); } } catch (WebException ex) { m_log.WarnFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex); return Tuple.Create(false, "web exception"); } catch (Exception ex) { m_log.WarnFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex); return Tuple.Create(false, "web exception"); } }
private Task <Tuple <EstablishPresenceResult, string> > LaunchNewEstablishChildTask(AvatarRemotePresence presence, SimpleRegionInfo region) { AgentCircuitData agent = _sp.ControllingClient.RequestClientInfo(); agent.BaseFolder = UUID.Zero; agent.InventoryFolder = UUID.Zero; agent.startpos = Scene.DEFAULT_CHILD_AGENT_POS; agent.child = true; agent.CapsPath = presence.PresenceInfo.CapsPath; return(_scene.SceneGridService.EstablishChildConnectionToRegionAsync(_sp, agent, region)); }
public async Task<bool> DoCloseAgentCallAsync(SimpleRegionInfo region, UUID id) { string uri = region.InsecurePublicHTTPServerURI + "/agent/" + id + "/" + region.RegionHandle.ToString() + "/"; HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri); request.Method = "DELETE"; request.Timeout = AGENT_UPDATE_TIMEOUT; request.ReadWriteTimeout = AGENT_UPDATE_TIMEOUT; request.Headers["authorization"] = GenerateAuthorization(); try { WebResponse webResponse = await request.GetResponseAsync(AGENT_UPDATE_TIMEOUT); if (webResponse == null) { m_log.Info("[REST COMMS]: Null reply on agent delete "); return false; } StreamReader sr = new StreamReader(webResponse.GetResponseStream()); string response = await sr.ReadToEndAsync(); response.Trim(); sr.Close(); return true; } catch (WebException ex) { m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex); } catch (Exception ex) { m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex); } return false; }
public async Task <Tuple <EstablishPresenceResult, string> > EstablishChildConnectionToRegionAsync(ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg) { string capsPath = CapsUtil.GetFullCapsSeedURL(reg.InsecurePublicHTTPServerURI, a.CapsPath); Tuple <bool, string> createResult = await m_interregionCommsOut.SendCreateRemoteChildAgentAsync(reg, a); if (createResult.Item1) { IPEndPoint endPoint = reg.ExternalEndPoint; IEventQueue eq = avatar.Scene.RequestModuleInterface <IEventQueue>(); if (!eq.EnableSimulator(reg.RegionHandle, endPoint, avatar.UUID)) { m_log.ErrorFormat("[INTERGRID]: Could not enqueue eq.EnableSimulator for {0}", avatar.Name); return(Tuple.Create(EstablishPresenceResult.ClientSignallingFailed, "Could not enqueue EnableSimulator")); } if (!eq.EstablishAgentCommunication(avatar.UUID, endPoint, capsPath)) { m_log.ErrorFormat("[INTERGRID]: Could not enqueue eq.EstablishAgentCommunication for {0}", avatar.Name); return(Tuple.Create(EstablishPresenceResult.ClientSignallingFailed, "Could not enqueue EstablishAgentCommunication")); } return(Tuple.Create(EstablishPresenceResult.Success, String.Empty)); } else { return(Tuple.Create(EstablishPresenceResult.ErrorInformingRegion, createResult.Item2)); } }