/// <summary> /// Disconnect from this simulator /// </summary> public void Disconnect(bool sendCloseCircuit) { if (connected) { connected = false; // Destroy the timers if (AckTimer != null) { AckTimer.Dispose(); } if (StatsTimer != null) { StatsTimer.Dispose(); } if (PingTimer != null) { PingTimer.Dispose(); } // Kill the current CAPS system if (Caps != null) { Caps.Disconnect(true); Caps = null; } if (sendCloseCircuit) { // Try to send the CloseCircuit notice CloseCircuitPacket close = new CloseCircuitPacket(); UDPPacketBuffer buf = new UDPPacketBuffer(ipEndPoint, false); buf.Data = close.ToBytes(); buf.DataLength = buf.Data.Length; AsyncBeginSend(buf); } // Shut the socket communication down Stop(); } }
/// <summary> /// /// </summary> /// <param name="capsEvent">Capability event name unregister the /// handler for</param> /// <param name="eventHandler">Callback to unregister</param> public void UnregisterEvent(string capsEvent, Caps.EventQueueCallback eventHandler) { lock (_EventTable) { if (_EventTable.ContainsKey(capsEvent) && _EventTable[capsEvent] != null) _EventTable[capsEvent] -= eventHandler; } }
/// <summary> /// Register an event handler /// </summary> /// <remarks>Use String.Empty to fire this event on every CAPS event</remarks> /// <param name="capsEvent">Capability event name to register the /// handler for</param> /// <param name="eventHandler">Callback to fire</param> public void RegisterEvent(string capsEvent, Caps.EventQueueCallback eventHandler) { lock (_EventTable) { if (_EventTable.ContainsKey(capsEvent)) _EventTable[capsEvent] += eventHandler; else _EventTable[capsEvent] = eventHandler; } }
/// <summary> /// Unregister a CAPS event handler. This is a low level event interface /// and should only be used if you are doing something not supported in /// libsecondlife /// </summary> /// <param name="capsEvent">Name of the CAPS event this callback is /// registered with</param> /// <param name="callback">Callback to stop firing events for</param> public void UnregisterEventCallback(string capsEvent, Caps.EventQueueCallback callback) { CapsEvents.UnregisterEvent(capsEvent, callback); }
/// <summary> /// Disconnect from this simulator /// </summary> public void Disconnect(bool sendCloseCircuit) { if (connected) { connected = false; // Destroy the timers if (AckTimer != null) AckTimer.Dispose(); if (StatsTimer != null) StatsTimer.Dispose(); if (PingTimer != null) PingTimer.Dispose(); // Kill the current CAPS system if (Caps != null) { Caps.Disconnect(true); Caps = null; } if (sendCloseCircuit) { // Try to send the CloseCircuit notice CloseCircuitPacket close = new CloseCircuitPacket(); UDPPacketBuffer buf = new UDPPacketBuffer(ipEndPoint, false); buf.Data = close.ToBytes(); buf.DataLength = buf.Data.Length; AsyncBeginSend(buf); } // Shut the socket communication down Stop(); } }
/// <summary> /// Register a CAPS event handler /// </summary> /// <param name="callback">Callback to fire when a CAPS event is received</param> public void RegisterEventCallback(Caps.EventQueueCallback callback) { lock (EventQueueCallbacks) EventQueueCallbacks.Add(callback); }
public void SetSeedCaps(string seedcaps) { if (Caps != null) { if (Caps._SeedCapsURI == seedcaps) return; Client.Log("Unexpected change of seed capability", Helpers.LogLevel.Warning); Caps.Disconnect(true); Caps = null; } if (Client.Settings.ENABLE_CAPS) { // Connect to the new CAPS system if (!String.IsNullOrEmpty(seedcaps)) Caps = new Caps(this, seedcaps); else Client.Log("Setting up a sim without a valid capabilities server!", Helpers.LogLevel.Error); } }
/// <summary> /// Disconnect from this simulator /// </summary> public void Disconnect() { connected = false; AckTimer.Stop(); StatsTimer.Stop(); if (Client.Settings.SEND_PINGS) PingTimer.Stop(); // Kill the current CAPS system if (SimCaps != null) { SimCaps.Disconnect(true); SimCaps = null; } // Make sure the socket is hooked up if (!Connection.Connected) return; // Try to send the CloseCircuit notice CloseCircuitPacket close = new CloseCircuitPacket(); // There's a high probability of this failing if the network is // disconnecting, so don't even bother logging the error try { Connection.Send(close.ToBytes()); } catch (SocketException) { } // Shut the socket communication down try { Connection.Shutdown(SocketShutdown.Both); } catch (SocketException) { } }
/// <summary> /// /// </summary> /// <param name="loginParams"></param> /// <param name="url"></param> /// <returns></returns> public bool Login(Dictionary<string, object> loginParams, string url) { // Rebuild the Dictionary<> in to a Hashtable for compatibility with XmlRpcCS Hashtable loginValues = new Hashtable(loginParams.Count); foreach (KeyValuePair<string, object> kvp in loginParams) { if (kvp.Value is IList) { IList list = ((IList)kvp.Value); ArrayList array = new ArrayList(list.Count); foreach (object obj in list) { array.Add(obj); } loginValues[kvp.Key] = array; } else { loginValues[kvp.Key] = kvp.Value; } } XmlRpcResponse result; XmlRpcRequest xmlrpc = new XmlRpcRequest(); xmlrpc.MethodName = "login_to_simulator"; xmlrpc.Params.Clear(); xmlrpc.Params.Add(loginValues); try { result = (XmlRpcResponse)xmlrpc.Send(url, LoginTimeout); } catch (Exception e) { LoginError = "XML-RPC Error: " + e.Message; LoginValues.Clear(); return false; } if (result.IsFault) { Client.Log("Fault " + result.FaultCode + ": " + result.FaultString, Helpers.LogLevel.Error); LoginError = "XML-RPC Fault: " + result.FaultCode + ": " + result.FaultString; LoginValues.Clear(); return false; } Hashtable values = (Hashtable)result.Value; foreach (DictionaryEntry entry in values) { LoginValues[(string)entry.Key] = entry.Value; } if ((string)LoginValues["login"] == "indeterminate") { //FIXME: We need to do another XML-RPC, handle this case LoginError = "Got a redirect, login with the official client to update"; return false; } else if ((string)LoginValues["login"] == "false") { LoginError = LoginValues["reason"] + ": " + LoginValues["message"]; return false; } else if ((string)LoginValues["login"] != "true") { LoginError = "Unknown error"; return false; } System.Text.RegularExpressions.Regex LLSDtoJSON = new System.Text.RegularExpressions.Regex(@"('|r([0-9])|r(\-))"); string json; Dictionary<string, object> jsonObject = null; LLVector3 vector = LLVector3.Zero; LLVector3 posVector = LLVector3.Zero; LLVector3 lookatVector = LLVector3.Zero; ulong regionHandle = 0; try { if (LoginValues.ContainsKey("look_at")) { // Replace LLSD variables with object representations // Convert LLSD string to JSON json = "{vector:" + LLSDtoJSON.Replace((string)LoginValues["look_at"], "$2") + "}"; // Convert JSON string to a JSON object jsonObject = JsonFacade.fromJSON(json); JSONArray jsonVector = (JSONArray)jsonObject["vector"]; // Convert the JSON object to an LLVector3 vector = new LLVector3(Convert.ToSingle(jsonVector[0], CultureInfo.InvariantCulture), Convert.ToSingle(jsonVector[1], CultureInfo.InvariantCulture), Convert.ToSingle(jsonVector[2], CultureInfo.InvariantCulture)); LoginValues["look_at"] = vector; } } catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Warning); LoginValues["look_at"] = null; } try { if (LoginValues.ContainsKey("home")) { Dictionary<string, object> home; // Convert LLSD string to JSON json = LLSDtoJSON.Replace((string)LoginValues["home"], "$2"); // Convert JSON string to an object jsonObject = JsonFacade.fromJSON(json); // Create the position vector JSONArray array = (JSONArray)jsonObject["position"]; posVector = new LLVector3(Convert.ToSingle(array[0], CultureInfo.InvariantCulture), Convert.ToSingle(array[1], CultureInfo.InvariantCulture), Convert.ToSingle(array[2], CultureInfo.InvariantCulture)); // Create the look_at vector array = (JSONArray)jsonObject["look_at"]; lookatVector = new LLVector3(Convert.ToSingle(array[0], CultureInfo.InvariantCulture), Convert.ToSingle(array[1], CultureInfo.InvariantCulture), Convert.ToSingle(array[2], CultureInfo.InvariantCulture)); // Create the regionhandle array = (JSONArray)jsonObject["region_handle"]; regionHandle = Helpers.UIntsToLong((uint)(int)array[0], (uint)(int)array[1]); Client.Self.Position = posVector; Client.Self.LookAt = lookatVector; // Create a dictionary to hold the home values home = new Dictionary<string, object>(); home["position"] = posVector; home["look_at"] = lookatVector; home["region_handle"] = regionHandle; LoginValues["home"] = home; } } catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Warning); LoginValues["home"] = null; } try { this.AgentID = new LLUUID((string)LoginValues["agent_id"]); this.SessionID = new LLUUID((string)LoginValues["session_id"]); Client.Self.ID = this.AgentID; // Names are wrapped in quotes now, have to strip those Client.Self.FirstName = ((string)LoginValues["first_name"]).Trim(new char[] { '"' }); Client.Self.LastName = ((string)LoginValues["last_name"]).Trim(new char[] { '"' }); Client.Self.LookAt = vector; Client.Self.HomePosition = posVector; Client.Self.HomeLookAt = lookatVector; // Get Inventory Root Folder Client.Log("Pulling root folder UUID from login data.", Helpers.LogLevel.Debug); ArrayList alInventoryRoot = (ArrayList)LoginValues["inventory-root"]; Hashtable htInventoryRoot = (Hashtable)alInventoryRoot[0]; Client.Self.InventoryRootFolderUUID = new LLUUID((string)htInventoryRoot["folder_id"]); // Connect to the sim given in the login reply Simulator simulator = new Simulator(Client, this.Callbacks, (uint)(int)LoginValues["circuit_code"], IPAddress.Parse((string)LoginValues["sim_ip"]), (int)LoginValues["sim_port"]); if (!simulator.Connected) { LoginError = "Unable to connect to the simulator"; return false; } simulator.Region.Handle = regionHandle; CurrentSim = simulator; // Simulator is successfully connected, add it to the list and set it as default Simulators.Add(simulator); if(LoginValues.ContainsKey("seed_capability") && (string)LoginValues["seed_capability"] != "") { CurrentCaps = new Caps(Client,simulator.Region,(string)LoginValues["seed_capability"], EventQueueCallbacks); } // Move our agent in to the sim to complete the connection Client.Self.CompleteAgentMovement(simulator); SendInitialPackets(); DisconnectTimer.Start(); connected = true; if (OnConnected != null) OnConnected(this.Client); return true; } catch (Exception e) { Client.Log("Login error: " + e.ToString(), Helpers.LogLevel.Error); return false; } }
/// <summary> /// /// </summary> /// <param name="ip"></param> /// <param name="port"></param> /// <param name="circuitCode"></param> /// <param name="setDefault"></param> /// <returns></returns> public Simulator Connect(IPAddress ip, ushort port, uint circuitCode, bool setDefault, string seedcaps) { Simulator simulator = new Simulator(Client, this.Callbacks, circuitCode, ip, (int)port); if (!simulator.Connected) { simulator = null; return null; } lock (Simulators) { Simulators.Add(simulator); } if (setDefault) { CurrentSim = simulator; if(CurrentCaps != null) CurrentCaps.Disconnect(); CurrentCaps = null; if(seedcaps != null && seedcaps != "") CurrentCaps = new Caps(Client,simulator.Region,seedcaps,EventQueueCallbacks); } DisconnectTimer.Start(); connected = true; return simulator; }
/// <summary> /// Shutdown will disconnect all the sims except for the current sim /// first, and then kill the connection to CurrentSim. /// </summary> private void Shutdown() { Client.Log("NetworkManager shutdown initiated", Helpers.LogLevel.Info); lock (Simulators) { // Disconnect all simulators except the current one foreach (Simulator simulator in Simulators) { // Don't disconnect the current sim, we'll use LogoutRequest for that if (simulator != null && simulator != CurrentSim) { DisconnectSim(simulator); // Fire the SimDisconnected event if a handler is registered if (OnSimDisconnected != null) { OnSimDisconnected(simulator, DisconnectType.NetworkTimeout); } } } Simulators.Clear(); } if (CurrentSim != null) { DisconnectSim(CurrentSim); CurrentSim = null; } if (CurrentCaps != null) { CurrentCaps.Disconnect(); CurrentCaps = null; } }
private void EventQueueHandler(string message, Hashtable body, Caps caps) { if (message == "TeleportFinish" && body.ContainsKey("Info")) { ArrayList infoList = (ArrayList)body["Info"]; Hashtable info = (Hashtable)infoList[0]; // Backwards compatibility hack TeleportFinishPacket packet = new TeleportFinishPacket(); packet.Info.SimIP = Helpers.BytesToUIntBig((byte[])info["SimIP"]); packet.Info.LocationID = Helpers.BytesToUInt((byte[])info["LocationID"]); packet.Info.TeleportFlags = Helpers.BytesToUInt((byte[])info["TeleportFlags"]); packet.Info.AgentID = (LLUUID)info["AgentID"]; packet.Info.RegionHandle = Helpers.BytesToUInt64((byte[])info["RegionHandle"]); packet.Info.SeedCapability = Helpers.StringToField((string)info["SeedCapability"]); packet.Info.SimPort = (ushort)(int)info["SimPort"]; packet.Info.SimAccess = (byte)(int)info["SimAccess"]; Client.DebugLog(String.Format( "Received a TeleportFinish event from {0}, SimIP: {1}, Location: {2}, RegionHandle: {3}", caps.Simulator.ToString(), packet.Info.SimIP, packet.Info.LocationID, packet.Info.RegionHandle)); TeleportHandler(packet, Client.Network.CurrentSim); } else if(message == "EstablishAgentCommunication" && Client.Settings.MULTIPLE_SIMS) { string ipAndPort = (string)body["sim-ip-and-port"]; string[] pieces = ipAndPort.Split(':'); IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(pieces[0]), Convert.ToInt32(pieces[1])); Simulator sim = Client.Network.FindSimulator(endPoint); if(sim == null) { Client.Log("Got EstablishAgentCommunication for unknown sim " + ipAndPort, Helpers.LogLevel.Error); } else { Client.Log("Got EstablishAgentCommunication for sim " + ipAndPort + ", seed cap " + (string)body["seed-capability"], Helpers.LogLevel.Info); sim.setSeedCaps((string)body["seed-capability"]); } } else { Client.Log("Received unhandled event " + message + " in the EventQueueHandler", Helpers.LogLevel.Warning); } }