/// <summary> /// Receive parcel voice cap /// </summary> /// <param name="client"></param> /// <param name="result"></param> /// <param name="error"></param> void pCap_OnComplete(OpenMetaverse.Http.CapsClient client, OpenMetaverse.StructuredData.OSD result, Exception error) { parcelCap.OnComplete -= new OpenMetaverse.Http.CapsClient.CompleteCallback(pCap_OnComplete); parcelCap = null; if (error != null) { Logger.Log("Region voice cap " + error.Message, Helpers.LogLevel.Error); return; } OpenMetaverse.StructuredData.OSDMap pMap = result as OpenMetaverse.StructuredData.OSDMap; regionName = pMap["region_name"].AsString(); ReportConnectionState(ConnectionState.RegionCapAvailable); if (pMap.ContainsKey("voice_credentials")) { OpenMetaverse.StructuredData.OSDMap cred = pMap["voice_credentials"] as OpenMetaverse.StructuredData.OSDMap; if (cred.ContainsKey("channel_uri")) { spatialUri = cred["channel_uri"].AsString(); } if (cred.ContainsKey("channel_credentials")) { spatialCredentials = cred["channel_credentials"].AsString(); } } if (string.IsNullOrEmpty(spatialUri)) { // "No voice chat allowed here"); return; } Logger.Log("Voice connecting for region " + regionName, Helpers.LogLevel.Info); // STEP 5 int reqId = SessionCreate( accountHandle, spatialUri, // uri "", // Channel name seems to be always null spatialCredentials, // spatialCredentials, // session password true, // Join Audio false, // Join Text ""); if (reqId < 0) { Logger.Log("Voice Session ReqID " + reqId.ToString(), Helpers.LogLevel.Error); } }
/// <summary> /// Request info from a parcel capability Uri. /// </summary> /// <param name="cap"></param> void RequestParcelInfo(Uri cap) { Logger.Log("Requesting region voice info", Helpers.LogLevel.Info); parcelCap = new CapsClient(cap, "RequestParcelInfo"); parcelCap.OnComplete += pCap_OnComplete; currentParcelCap = cap; parcelCap.PostRequestAsync(new OSD(), OSDFormat.Xml, 10000); }
/// <summary> /// Handle completion of main voice cap request. /// </summary> /// <param name="client"></param> /// <param name="result"></param> /// <param name="error"></param> void cClient_OnComplete(OpenMetaverse.Http.CapsClient client, OpenMetaverse.StructuredData.OSD result, Exception error) { if (error != null) { Logger.Log("Voice cap error " + error.Message, Helpers.LogLevel.Error); return; } Logger.Log("Voice provisioned", Helpers.LogLevel.Info); ReportConnectionState(ConnectionState.Provisioned); OpenMetaverse.StructuredData.OSDMap pMap = result as OpenMetaverse.StructuredData.OSDMap; // We can get back 4 interesting values: // voice_sip_uri_hostname // voice_account_server_name (actually a full URI) // username // password if (pMap.ContainsKey("voice_sip_uri_hostname")) { sipServer = pMap["voice_sip_uri_hostname"].AsString(); } if (pMap.ContainsKey("voice_account_server_name")) { acctServer = pMap["voice_account_server_name"].AsString(); } voiceUser = pMap["username"].AsString(); voicePassword = pMap["password"].AsString(); // Start the SLVoice daemon slvoicePath = GetVoiceDaemonPath(); // Test if the executable exists if (!System.IO.File.Exists(slvoicePath)) { Logger.Log("SLVoice is missing", Helpers.LogLevel.Error); return; } // STEP 1 StartDaemon(slvoicePath, slvoiceArgs); }
/// <summary> /// Tells the sim what UI language is used, and if it's ok to share that with scripts /// </summary> /// <param name="language">Two letter language code</param> /// <param name="isPublic">Share language info with scripts</param> public void UpdateAgentLanguage(string language, bool isPublic) { try { UpdateAgentLanguageMessage msg = new UpdateAgentLanguageMessage(); msg.Language = language; msg.LanguagePublic = isPublic; Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("UpdateAgentLanguage"); if (url != null) { CapsClient request = new CapsClient(url); request.BeginGetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } } catch (Exception ex) { Logger.Log("Failes to update agent language", Helpers.LogLevel.Error, Client, ex); } }
private void BeginLogin() { LoginParams loginParams = CurrentContext.Value; // Generate a random ID to identify this login attempt loginParams.LoginID = UUID.Random(); CurrentContext = loginParams; #region Sanity Check loginParams if (loginParams.Options == null) loginParams.Options = new List<string>().ToArray(); // Convert the password to MD5 if it isn't already if (loginParams.Password.Length != 35 && !loginParams.Password.StartsWith("$1$")) loginParams.Password = Utils.MD5(loginParams.Password); if (loginParams.ViewerDigest == null) loginParams.ViewerDigest = String.Empty; if (loginParams.Version == null) loginParams.Version = String.Empty; if (loginParams.UserAgent == null) loginParams.UserAgent = String.Empty; if (loginParams.Platform == null) loginParams.Platform = String.Empty; if (loginParams.MAC == null) loginParams.MAC = String.Empty; if (loginParams.Channel == null) loginParams.Channel = String.Empty; if (loginParams.Author == null) loginParams.Author = String.Empty; #endregion // TODO: Allow a user callback to be defined for handling the cert ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy(); // Even though this will compile on Mono 2.4, it throws a runtime exception //ServicePointManager.ServerCertificateValidationCallback = TrustAllCertificatePolicy.TrustAllCertificateHandler; if (Client.Settings.USE_LLSD_LOGIN) { #region LLSD Based Login // Create the CAPS login structure OSDMap loginLLSD = new OSDMap(); loginLLSD["first"] = OSD.FromString(loginParams.FirstName); loginLLSD["last"] = OSD.FromString(loginParams.LastName); loginLLSD["passwd"] = OSD.FromString(loginParams.Password); loginLLSD["start"] = OSD.FromString(loginParams.Start); loginLLSD["channel"] = OSD.FromString(loginParams.Channel); loginLLSD["version"] = OSD.FromString(loginParams.Version); loginLLSD["platform"] = OSD.FromString(loginParams.Platform); loginLLSD["mac"] = OSD.FromString(loginParams.MAC); loginLLSD["agree_to_tos"] = OSD.FromBoolean(loginParams.AgreeToTos); loginLLSD["read_critical"] = OSD.FromBoolean(loginParams.ReadCritical); loginLLSD["viewer_digest"] = OSD.FromString(loginParams.ViewerDigest); loginLLSD["id0"] = OSD.FromString(loginParams.ID0); // Create the options LLSD array OSDArray optionsOSD = new OSDArray(); for (int i = 0; i < loginParams.Options.Length; i++) optionsOSD.Add(OSD.FromString(loginParams.Options[i])); foreach (string[] callbackOpts in CallbackOptions.Values) { if (callbackOpts != null) { for (int i = 0; i < callbackOpts.Length; i++) { if (!optionsOSD.Contains(callbackOpts[i])) optionsOSD.Add(callbackOpts[i]); } } } loginLLSD["options"] = optionsOSD; // Make the CAPS POST for login Uri loginUri; try { loginUri = new Uri(loginParams.URI); } catch (Exception ex) { Logger.Log(String.Format("Failed to parse login URI {0}, {1}", loginParams.URI, ex.Message), Helpers.LogLevel.Error, Client); return; } CapsClient loginRequest = new CapsClient(loginUri); loginRequest.OnComplete += new CapsClient.CompleteCallback(LoginReplyLLSDHandler); loginRequest.UserData = CurrentContext; UpdateLoginStatus(LoginStatus.ConnectingToLogin, String.Format("Logging in as {0} {1}...", loginParams.FirstName, loginParams.LastName)); loginRequest.BeginGetResponse(loginLLSD, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); #endregion } else { #region XML-RPC Based Login Code // Create the Hashtable for XmlRpcCs Hashtable loginXmlRpc = new Hashtable(); loginXmlRpc["first"] = loginParams.FirstName; loginXmlRpc["last"] = loginParams.LastName; loginXmlRpc["passwd"] = loginParams.Password; loginXmlRpc["start"] = loginParams.Start; loginXmlRpc["channel"] = loginParams.Channel; loginXmlRpc["version"] = loginParams.Version; loginXmlRpc["platform"] = loginParams.Platform; loginXmlRpc["mac"] = loginParams.MAC; if (loginParams.AgreeToTos) loginXmlRpc["agree_to_tos"] = "true"; if (loginParams.ReadCritical) loginXmlRpc["read_critical"] = "true"; loginXmlRpc["id0"] = loginParams.ID0; loginXmlRpc["last_exec_event"] = 0; // Create the options array ArrayList options = new ArrayList(); for (int i = 0; i < loginParams.Options.Length; i++) options.Add(loginParams.Options[i]); foreach (string[] callbackOpts in CallbackOptions.Values) { if (callbackOpts != null) { for (int i = 0; i < callbackOpts.Length; i++) { if (!options.Contains(callbackOpts[i])) options.Add(callbackOpts[i]); } } } loginXmlRpc["options"] = options; try { ArrayList loginArray = new ArrayList(1); loginArray.Add(loginXmlRpc); XmlRpcRequest request = new XmlRpcRequest(CurrentContext.Value.MethodName, loginArray); // Start the request Thread requestThread = new Thread( delegate() { try { LoginReplyXmlRpcHandler( request.Send(CurrentContext.Value.URI, CurrentContext.Value.Timeout), loginParams); } catch (WebException e) { UpdateLoginStatus(LoginStatus.Failed, "Error opening the login server connection: " + e.Message); } }); requestThread.Name = "XML-RPC Login"; requestThread.Start(); } catch (Exception e) { UpdateLoginStatus(LoginStatus.Failed, "Error opening the login server connection: " + e); } #endregion } }
private void ProvisionCapsResponse(CapsClient client, OSD response, Exception error) { if (response is OSDMap) { OSDMap respTable = (OSDMap)response; if (OnProvisionAccount != null) { try { OnProvisionAccount(respTable["username"].AsString(), respTable["password"].AsString()); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } } }
/// <summary> /// Start a friends conference /// </summary> /// <param name="participants"><seealso cref="UUID"/> List of UUIDs to start a conference with</param> /// <param name="tmp_session_id">the temportary session ID returned in the <see cref="OnJoinedGroupChat"/> callback></param> public void StartIMConference(List<UUID> participants, UUID tmp_session_id) { if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null) throw new Exception("ChatSessionRequest capability is not currently available"); Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("ChatSessionRequest"); if (url != null) { ChatSessionRequestStartConference startConference = new ChatSessionRequestStartConference(); startConference.AgentsBlock = new UUID[participants.Count]; for (int i = 0; i < participants.Count; i++) startConference.AgentsBlock[i] = participants[i]; startConference.SessionID = tmp_session_id; CapsClient request = new CapsClient(url); request.BeginGetResponse(startConference.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } else { throw new Exception("ChatSessionRequest capability is not currently available"); } }
/// <summary> /// Moderate a chat session /// </summary> /// <param name="sessionID">the <see cref="UUID"/> of the session to moderate, for group chats this will be the groups UUID</param> /// <param name="memberID">the <see cref="UUID"/> of the avatar to moderate</param> /// <param name="key">Either "voice" to moderate users voice, or "text" to moderate users text session</param> /// <param name="moderate">true to moderate (silence user), false to allow avatar to speak</param> public void ModerateChatSessions(UUID sessionID, UUID memberID, string key, bool moderate) { if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null) throw new Exception("ChatSessionRequest capability is not currently available"); Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("ChatSessionRequest"); if (url != null) { ChatSessionRequestMuteUpdate req = new ChatSessionRequestMuteUpdate(); req.RequestKey = key; req.RequestValue = moderate; req.SessionID = sessionID; req.AgentID = memberID; CapsClient request = new CapsClient(url); request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } else { throw new Exception("ChatSessionRequest capability is not currently available"); } }
private void UploadInventoryAssetResponse(CapsClient client, OSD result, Exception error) { OSDMap contents = result as OSDMap; KeyValuePair<InventoryUploadedAssetCallback, byte[]> kvp = (KeyValuePair<InventoryUploadedAssetCallback, byte[]>)(((object[])client.UserData)[0]); InventoryUploadedAssetCallback callback = kvp.Key; byte[] itemData = (byte[])kvp.Value; if (error == null && contents != null) { string status = contents["state"].AsString(); if (status == "upload") { Uri uploadURL = contents["uploader"].AsUri(); if (uploadURL != null) { // This makes the assumption that all uploads go to CurrentSim, to avoid // the problem of HttpRequestState not knowing anything about simulators CapsClient upload = new CapsClient(uploadURL); upload.OnComplete += UploadInventoryAssetResponse; upload.UserData = new object[2] { kvp, (UUID)(((object[])client.UserData)[1]) }; upload.BeginGetResponse(itemData, "application/octet-stream", Client.Settings.CAPS_TIMEOUT); } else { try { callback(false, "Missing uploader URL", UUID.Zero, UUID.Zero); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } } else if (status == "complete") { if (contents.ContainsKey("new_asset")) { // Request full item update so we keep store in sync RequestFetchInventory((UUID)(((object[])client.UserData)[1]), contents["new_asset"].AsUUID()); try { callback(true, String.Empty, (UUID)(((object[])client.UserData)[1]), contents["new_asset"].AsUUID()); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } else { try { callback(false, "Failed to parse asset and item UUIDs", UUID.Zero, UUID.Zero); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } } else { try { callback(false, status, UUID.Zero, UUID.Zero); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } } else { string message = "Unrecognized or empty response"; if (error != null) { if (error is WebException) message = ((HttpWebResponse)((WebException)error).Response).StatusDescription; if (message == null || message == "None") message = error.Message; } try { callback(false, message, UUID.Zero, UUID.Zero); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } }
public void RequestUploadBakedTexture(byte[] textureData, BakedTextureUploadedCallback callback) { Uri url = null; Caps caps = Client.Network.CurrentSim.Caps; if (caps != null) url = caps.CapabilityURI("UploadBakedTexture"); if (url != null) { // Fetch the uploader capability CapsClient request = new CapsClient(url); request.OnComplete += delegate(CapsClient client, OSD result, Exception error) { if (error == null && result is OSDMap) { UploadBakedTextureMessage message = new UploadBakedTextureMessage(); message.Deserialize((OSDMap)result); if (message.Request.State == "upload") { Uri uploadUrl = ((UploaderRequestUpload)message.Request).Url; if (uploadUrl != null) { // POST the asset data CapsClient upload = new CapsClient(uploadUrl); upload.OnComplete += delegate(CapsClient client2, OSD result2, Exception error2) { if (error2 == null && result2 is OSDMap) { UploadBakedTextureMessage message2 = new UploadBakedTextureMessage(); message2.Deserialize((OSDMap)result2); if (message2.Request.State == "complete") { callback(((UploaderRequestComplete)message2.Request).AssetID); return; } } Logger.Log("Bake upload failed during asset upload", Helpers.LogLevel.Warning, Client); callback(UUID.Zero); }; upload.BeginGetResponse(textureData, "application/octet-stream", Client.Settings.CAPS_TIMEOUT); return; } } } Logger.Log("Bake upload failed during uploader retrieval", Helpers.LogLevel.Warning, Client); callback(UUID.Zero); }; request.BeginGetResponse(new OSDMap(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } else { Logger.Log("UploadBakedTexture not available, falling back to UDP method", Helpers.LogLevel.Info, Client); ThreadPool.QueueUserWorkItem( delegate(object o) { UUID transactionID = UUID.Random(); BakedTextureUploadedCallback uploadCallback = (BakedTextureUploadedCallback)o; AutoResetEvent uploadEvent = new AutoResetEvent(false); EventHandler<AssetUploadEventArgs> udpCallback = delegate(object sender, AssetUploadEventArgs e) { if (e.Upload.ID == transactionID) { uploadEvent.Set(); uploadCallback(e.Upload.Success ? e.Upload.AssetID : UUID.Zero); } }; AssetUploaded += udpCallback; UUID assetID; bool success; try { RequestUpload(out assetID, AssetType.Texture, textureData, true, transactionID); success = uploadEvent.WaitOne(Client.Settings.TRANSFER_TIMEOUT, false); } catch (Exception) { success = false; } AssetUploaded -= udpCallback; if (!success) uploadCallback(UUID.Zero); }, callback ); } }
/// <summary> /// Request a copy of an asset embedded within a notecard /// </summary> /// <param name="objectID">Usually UUID.Zero for copying an asset from a notecard</param> /// <param name="notecardID">UUID of the notecard to request an asset from</param> /// <param name="folderID">Target folder for asset to go to in your inventory</param> /// <param name="itemID">UUID of the embedded asset</param> /// <param name="callback">callback to run when item is copied to inventory</param> public void RequestCopyItemFromNotecard(UUID objectID, UUID notecardID, UUID folderID, UUID itemID, ItemCopiedCallback callback) { _ItemCopiedCallbacks[0] = callback; //Notecards always use callback ID 0 Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("CopyInventoryFromNotecard"); if (url != null) { CopyInventoryFromNotecardMessage message = new CopyInventoryFromNotecardMessage(); message.CallbackID = 0; message.FolderID = folderID; message.ItemID = itemID; message.NotecardID = notecardID; message.ObjectID = objectID; CapsClient request = new CapsClient(url); request.BeginGetResponse(message.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } else { CopyInventoryFromNotecardPacket copy = new CopyInventoryFromNotecardPacket(); copy.AgentData.AgentID = Client.Self.AgentID; copy.AgentData.SessionID = Client.Self.SessionID; copy.NotecardData.ObjectID = objectID; copy.NotecardData.NotecardItemID = notecardID; copy.InventoryData = new CopyInventoryFromNotecardPacket.InventoryDataBlock[1]; copy.InventoryData[0] = new CopyInventoryFromNotecardPacket.InventoryDataBlock(); copy.InventoryData[0].FolderID = folderID; copy.InventoryData[0].ItemID = itemID; Client.Network.SendPacket(copy); } }
/// <summary> /// Update an existing script in an task Inventory /// </summary> /// <param name="data">A byte[] array containing the encoded scripts contents</param> /// <param name="itemID">the itemID of the script</param> /// <param name="taskID">UUID of the prim containting the script</param> /// <param name="mono">if true, sets the script content to run on the mono interpreter</param> /// <param name="running">if true, sets the script to running</param> /// <param name="callback"></param> public void RequestUpdateScriptTask(byte[] data, UUID itemID, UUID taskID, bool mono, bool running, ScriptUpdatedCallback callback) { Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("UpdateScriptTask"); if (url != null) { UpdateScriptTaskUpdateMessage msg = new UpdateScriptTaskUpdateMessage(); msg.ItemID = itemID; msg.TaskID = taskID; msg.ScriptRunning = running; msg.Target = mono ? "mono" : "lsl2"; CapsClient request = new CapsClient(url); request.OnComplete += new CapsClient.CompleteCallback(UpdateScriptAgentInventoryResponse); request.UserData = new object[2] { new KeyValuePair<ScriptUpdatedCallback, byte[]>(callback, data), itemID }; request.BeginGetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } else { throw new Exception("UpdateScriptTask capability is not currently available"); } }
/// <summary> /// Initates request to set a new display name /// </summary> /// <param name="oldName">Previous display name</param> /// <param name="newName">Desired new display name</param> public void SetDisplayName(string oldName, string newName) { Uri uri; if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null || (uri = Client.Network.CurrentSim.Caps.CapabilityURI("SetDisplayName")) == null) { Logger.Log("Unable to invoke SetDisplyName capability at this time", Helpers.LogLevel.Warning, Client); return; } SetDisplayNameMessage msg = new SetDisplayNameMessage(); msg.OldDisplayName = oldName; msg.NewDisplayName = newName; CapsClient cap = new CapsClient(uri); cap.BeginGetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); }
/// <summary> /// Sets agents maturity access level /// </summary> /// <param name="access">PG, M or A</param> /// <param name="callback">Callback function</param> public void SetAgentAccess(string access, AgentAccessCallback callback) { if (Client == null || !Client.Network.Connected || Client.Network.CurrentSim.Caps == null) return; Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("UpdateAgentInformation"); if (url == null) return; CapsClient request = new CapsClient(url); request.OnComplete += (client, result, error) => { bool success = true; if (error == null && result is OSDMap) { var map = ((OSDMap)result)["access_prefs"]; agentAccess = ((OSDMap)map)["max"]; Logger.Log("Max maturity access set to " + agentAccess, Helpers.LogLevel.Info, Client ); } else if (error == null) { Logger.Log("Max maturity unchanged at " + agentAccess, Helpers.LogLevel.Info, Client); } else { Logger.Log("Failed setting max maturity access.", Helpers.LogLevel.Warning, Client); success = false; } if (callback != null) { try { callback(new AgentAccessEventArgs(success, agentAccess)); } catch { } } }; OSDMap req = new OSDMap(); OSDMap prefs = new OSDMap(); prefs["max"] = access; req["access_prefs"] = prefs; request.BeginGetResponse(req, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); }
private void GatherLastNamesResponse(CapsClient client, OSD response, Exception error) { if (response is OSDMap) { } }
private void GatherErrorMessagesResponse(CapsClient client, OSD response, Exception error) { if (response is OSDMap) { _initializing++; } }
private void GatherErrorMessages() { if (_caps.GetErrorCodes == null) throw new InvalidOperationException("access denied"); // this should work even for not-approved users CapsClient request = new CapsClient(_caps.GetErrorCodes); request.OnComplete += new CapsClient.CompleteCallback(GatherErrorMessagesResponse); request.BeginGetResponse(REQUEST_TIMEOUT); }
/// <summary> /// Upload new gesture asset for an inventory gesture item /// </summary> /// <param name="data">Encoded gesture asset</param> /// <param name="gestureID">Gesture inventory UUID</param> /// <param name="callback">Callback whick will be called when upload is complete</param> public void RequestUploadGestureAsset(byte[] data, UUID gestureID, InventoryUploadedAssetCallback callback) { if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null) throw new Exception("UpdateGestureAgentInventory capability is not currently available"); Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("UpdateGestureAgentInventory"); if (url != null) { OSDMap query = new OSDMap(); query.Add("item_id", OSD.FromUUID(gestureID)); // Make the request CapsClient request = new CapsClient(url); request.OnComplete += UploadInventoryAssetResponse; request.UserData = new object[] { new KeyValuePair<InventoryUploadedAssetCallback, byte[]>(callback, data), gestureID }; request.BeginGetResponse(query, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } else { throw new Exception("UpdateGestureAgentInventory capability is not currently available"); } }
/// <summary> /// /// </summary> /// <param name="layer"></param> public void RequestMapLayer(GridLayerType layer) { Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("MapLayer"); if (url != null) { OSDMap body = new OSDMap(); body["Flags"] = OSD.FromInteger((int)layer); CapsClient request = new CapsClient(url); request.OnComplete += new CapsClient.CompleteCallback(MapLayerResponseHandler); request.BeginGetResponse(body, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } }
private void CreateItemFromAssetResponse(CapsClient client, OSD result, Exception error) { object[] args = (object[])client.UserData; ItemCreatedFromAssetCallback callback = (ItemCreatedFromAssetCallback)args[0]; byte[] itemData = (byte[])args[1]; int millisecondsTimeout = (int)args[2]; OSDMap request = (OSDMap)args[3]; if (result == null) { try { callback(false, error.Message, UUID.Zero, UUID.Zero); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } return; } OSDMap contents = (OSDMap)result; string status = contents["state"].AsString().ToLower(); if (status == "upload") { string uploadURL = contents["uploader"].AsString(); Logger.DebugLog("CreateItemFromAsset: uploading to " + uploadURL); // This makes the assumption that all uploads go to CurrentSim, to avoid // the problem of HttpRequestState not knowing anything about simulators CapsClient upload = new CapsClient(new Uri(uploadURL)); upload.OnComplete += CreateItemFromAssetResponse; upload.UserData = new object[] { callback, itemData, millisecondsTimeout, request }; upload.BeginGetResponse(itemData, "application/octet-stream", millisecondsTimeout); } else if (status == "complete") { Logger.DebugLog("CreateItemFromAsset: completed"); if (contents.ContainsKey("new_inventory_item") && contents.ContainsKey("new_asset")) { // Request full update on the item in order to update the local store RequestFetchInventory(contents["new_inventory_item"].AsUUID(), Client.Self.AgentID); try { callback(true, String.Empty, contents["new_inventory_item"].AsUUID(), contents["new_asset"].AsUUID()); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } else { try { callback(false, "Failed to parse asset and item UUIDs", UUID.Zero, UUID.Zero); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } } else { // Failure try { callback(false, status, UUID.Zero, UUID.Zero); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } }
protected void MapLayerResponseHandler(CapsClient client, OSD result, Exception error) { if (result == null) { Logger.Log("MapLayerResponseHandler error: " + error.Message + ": " + error.StackTrace, Helpers.LogLevel.Error, Client); return; } OSDMap body = (OSDMap)result; OSDArray layerData = (OSDArray)body["LayerData"]; if (m_GridLayer != null) { for (int i = 0; i < layerData.Count; i++) { OSDMap thisLayerData = (OSDMap)layerData[i]; GridLayer layer; layer.Bottom = thisLayerData["Bottom"].AsInteger(); layer.Left = thisLayerData["Left"].AsInteger(); layer.Top = thisLayerData["Top"].AsInteger(); layer.Right = thisLayerData["Right"].AsInteger(); layer.ImageID = thisLayerData["ImageID"].AsUUID(); OnGridLayer(new GridLayerEventArgs(layer)); } } if (body.ContainsKey("MapBlocks")) { // TODO: At one point this will become activated Logger.Log("Got MapBlocks through CAPS, please finish this function!", Helpers.LogLevel.Error, Client); } }
private void UpdateScriptAgentInventoryResponse(CapsClient client, OSD result, Exception error) { KeyValuePair<ScriptUpdatedCallback, byte[]> kvp = (KeyValuePair<ScriptUpdatedCallback, byte[]>)(((object[])client.UserData)[0]); ScriptUpdatedCallback callback = kvp.Key; byte[] itemData = (byte[])kvp.Value; if (result == null) { try { callback(false, error.Message, false, null, UUID.Zero, UUID.Zero); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } return; } OSDMap contents = (OSDMap)result; string status = contents["state"].AsString(); if (status == "upload") { string uploadURL = contents["uploader"].AsString(); CapsClient upload = new CapsClient(new Uri(uploadURL)); upload.OnComplete += new CapsClient.CompleteCallback(UpdateScriptAgentInventoryResponse); upload.UserData = new object[2] { kvp, (UUID)(((object[])client.UserData)[1]) }; upload.BeginGetResponse(itemData, "application/octet-stream", Client.Settings.CAPS_TIMEOUT); } else if (status == "complete" && callback != null) { if (contents.ContainsKey("new_asset")) { // Request full item update so we keep store in sync RequestFetchInventory((UUID)(((object[])client.UserData)[1]), contents["new_asset"].AsUUID()); try { List<string> compileErrors = null; if (contents.ContainsKey("errors")) { OSDArray errors = (OSDArray)contents["errors"]; compileErrors = new List<string>(errors.Count); for (int i = 0; i < errors.Count; i++) { compileErrors.Add(errors[i].AsString()); } } callback(true, status, contents["compiled"].AsBoolean(), compileErrors, (UUID)(((object[])client.UserData)[1]), contents["new_asset"].AsUUID()); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } else { try { callback(false, "Failed to parse asset UUID", false, null, UUID.Zero, UUID.Zero); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } } else if (callback != null) { try { callback(false, status, false, null, UUID.Zero, UUID.Zero); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } }
/// <summary> /// Update current URL of the previously set prim media /// </summary> /// <param name="primID">UUID of the prim</param> /// <param name="newURL">Set current URL to this</param> /// <param name="face">Prim face number</param> /// <param name="sim">Simulator in which prim is located</param> public void NavigateObjectMedia(UUID primID, int face, string newURL, Simulator sim) { Uri url; if (sim.Caps != null && null != (url = sim.Caps.CapabilityURI("ObjectMediaNavigate"))) { ObjectMediaNavigateMessage req = new ObjectMediaNavigateMessage(); req.PrimID = primID; req.URL = newURL; req.Face = face; CapsClient request = new CapsClient(url); request.OnComplete += (CapsClient client, OSD result, Exception error) => { if (error != null) { Logger.Log("ObjectMediaNavigate: " + error.Message, Helpers.LogLevel.Error, Client); } }; request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } else { Logger.Log("ObjectMediaNavigate capability not available", Helpers.LogLevel.Error, Client); } }
/// <summary> /// Accept invite for to a chatterbox session /// </summary> /// <param name="session_id"><seealso cref="UUID"/> of session to accept invite to</param> public void ChatterBoxAcceptInvite(UUID session_id) { if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null) throw new Exception("ChatSessionRequest capability is not currently available"); Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("ChatSessionRequest"); if (url != null) { ChatSessionAcceptInvitation acceptInvite = new ChatSessionAcceptInvitation(); acceptInvite.SessionID = session_id; CapsClient request = new CapsClient(url); request.BeginGetResponse(acceptInvite.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } else { throw new Exception("ChatSessionRequest capability is not currently available"); } }
/// <summary> /// Set object media /// </summary> /// <param name="primID">UUID of the prim</param> /// <param name="faceMedia">Array the length of prims number of faces. Null on face indexes where there is /// no media, <seealso cref="MediaEntry"/> on faces which contain the media</param> /// <param name="sim">Simulatior in which prim is located</param> public void UpdateObjectMedia(UUID primID, MediaEntry[] faceMedia, Simulator sim) { Uri url; if (sim.Caps != null && null != (url = sim.Caps.CapabilityURI("ObjectMedia"))) { ObjectMediaUpdate req = new ObjectMediaUpdate(); req.PrimID = primID; req.FaceMedia = faceMedia; req.Verb = "UPDATE"; CapsClient request = new CapsClient(url); request.OnComplete += (CapsClient client, OSD result, Exception error) => { if (error != null) { Logger.Log("ObjectMediaUpdate: " + error.Message, Helpers.LogLevel.Error, Client); } }; request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } else { Logger.Log("ObjectMedia capability not available", Helpers.LogLevel.Error, Client); } }
/// <summary> /// Fetches resource usage by agents attachmetns /// </summary> /// <param name="callback">Called when the requested information is collected</param> public void GetAttachmentResources(AttachmentResourcesCallback callback) { try { Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("AttachmentResources"); CapsClient request = new CapsClient(url); request.OnComplete += delegate(CapsClient client, OSD result, Exception error) { try { if (result == null || error != null) { callback(false, null); } AttachmentResourcesMessage info = AttachmentResourcesMessage.FromOSD(result); callback(true, info); } catch (Exception ex) { Logger.Log("Failed fetching AttachmentResources", Helpers.LogLevel.Error, Client, ex); callback(false, null); } }; request.BeginGetResponse(Client.Settings.CAPS_TIMEOUT); } catch (Exception ex) { Logger.Log("Failed fetching AttachmentResources", Helpers.LogLevel.Error, Client, ex); callback(false, null); } }
/// <summary> /// Retrieve information about object media /// </summary> /// <param name="primID">UUID of the primitive</param> /// <param name="sim">Simulator where prim is located</param> /// <param name="callback">Call this callback when done</param> public void RequestObjectMedia(UUID primID, Simulator sim, ObjectMediaCallback callback) { Uri url; if (sim.Caps != null && null != (url = sim.Caps.CapabilityURI("ObjectMedia"))) { ObjectMediaRequest req = new ObjectMediaRequest(); req.PrimID = primID; req.Verb = "GET"; CapsClient request = new CapsClient(url); request.OnComplete += (CapsClient client, OSD result, Exception error) => { if (result == null) { Logger.Log("Failed retrieving ObjectMedia data", Helpers.LogLevel.Error, Client); try { callback(false, string.Empty, null); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); } return; } ObjectMediaMessage msg = new ObjectMediaMessage(); msg.Deserialize((OSDMap)result); if (msg.Request is ObjectMediaResponse) { ObjectMediaResponse response = (ObjectMediaResponse)msg.Request; if (Client.Settings.OBJECT_TRACKING) { Primitive prim = sim.ObjectsPrimitives.Find((Primitive p) => { return p.ID == primID; }); if (prim != null) { prim.MediaVersion = response.Version; prim.FaceMedia = response.FaceMedia; } } try { callback(true, response.Version, response.FaceMedia); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); } } else { try { callback(false, string.Empty, null); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); } } }; request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } else { Logger.Log("ObjectMedia capability not available", Helpers.LogLevel.Error, Client); try { callback(false, string.Empty, null); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client); } } }
/// <summary> /// Handle response from LLSD login replies /// </summary> /// <param name="client"></param> /// <param name="result"></param> /// <param name="error"></param> private void LoginReplyLLSDHandler(CapsClient client, OSD result, Exception error) { if (error == null) { if (result != null && result.Type == OSDType.Map) { OSDMap map = (OSDMap)result; OSD osd; LoginResponseData data = new LoginResponseData(); data.Parse(map); if (map.TryGetValue("login", out osd)) { bool loginSuccess = osd.AsBoolean(); bool redirect = (osd.AsString() == "indeterminate"); if (redirect) { // Login redirected // Make the next login URL jump UpdateLoginStatus(LoginStatus.Redirecting, data.Message); LoginParams loginParams = CurrentContext.Value; loginParams.URI = LoginResponseData.ParseString("next_url", map); //CurrentContext.Params.MethodName = LoginResponseData.ParseString("next_method", map); // Sleep for some amount of time while the servers work int seconds = (int)LoginResponseData.ParseUInt("next_duration", map); Logger.Log("Sleeping for " + seconds + " seconds during a login redirect", Helpers.LogLevel.Info); Thread.Sleep(seconds * 1000); // Ignore next_options for now CurrentContext = loginParams; BeginLogin(); } else if (loginSuccess) { // Login succeeded // Fire the login callback if (OnLoginResponse != null) { try { OnLoginResponse(loginSuccess, redirect, data.Message, data.Reason, data); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex); } } // These parameters are stored in NetworkManager, so instead of registering // another callback for them we just set the values here CircuitCode = (uint)data.CircuitCode; LoginSeedCapability = data.SeedCapability; UpdateLoginStatus(LoginStatus.ConnectingToSim, "Connecting to simulator..."); ulong handle = Utils.UIntsToLong((uint)data.RegionX, (uint)data.RegionY); if (data.SimIP != null && data.SimPort != 0) { // Connect to the sim given in the login reply if (Connect(data.SimIP, (ushort)data.SimPort, handle, true, LoginSeedCapability) != null) { // Request the economy data right after login SendPacket(new EconomyDataRequestPacket()); // Update the login message with the MOTD returned from the server UpdateLoginStatus(LoginStatus.Success, data.Message); } else { UpdateLoginStatus(LoginStatus.Failed, "Unable to establish a UDP connection to the simulator"); } } else { UpdateLoginStatus(LoginStatus.Failed, "Login server did not return a simulator address"); } } else { // Login failed // Make sure a usable error key is set if (data.Reason != String.Empty) InternalErrorKey = data.Reason; else InternalErrorKey = "unknown"; UpdateLoginStatus(LoginStatus.Failed, data.Message); } } else { // Got an LLSD map but no login value UpdateLoginStatus(LoginStatus.Failed, "login parameter missing in the response"); } } else { // No LLSD response InternalErrorKey = "bad response"; UpdateLoginStatus(LoginStatus.Failed, "Empty or unparseable login response"); } } else { // Connection error InternalErrorKey = "no connection"; UpdateLoginStatus(LoginStatus.Failed, error.Message); } }
/// <summary> /// Request retrieval of display names (max 90 names per request) /// </summary> /// <param name="ids">List of UUIDs to lookup</param> /// <param name="callback">Callback to report result of the operation</param> public void GetDisplayNames(List<UUID> ids, DisplayNamesCallback callback) { if (!DisplayNamesAvailable() || ids.Count == 0) { callback(false, null, null); } StringBuilder query = new StringBuilder(); for (int i = 0; i < ids.Count && i < 90; i++) { query.AppendFormat("ids={0}", ids[i]); if (i < ids.Count - 1) { query.Append("&"); } } Uri uri = new Uri(Client.Network.CurrentSim.Caps.CapabilityURI("GetDisplayNames").AbsoluteUri + "/?" + query); CapsClient cap = new CapsClient(uri); cap.OnComplete += (CapsClient client, OSD result, Exception error) => { try { if (error != null) throw error; GetDisplayNamesMessage msg = new GetDisplayNamesMessage(); msg.Deserialize((OSDMap) result); callback(true, msg.Agents, msg.BadIDs); } catch (Exception ex) { Logger.Log("Failed to call GetDisplayNames capability: ", Helpers.LogLevel.Warning, Client, ex); callback(false, null, null); } }; cap.BeginGetResponse(null, String.Empty, Client.Settings.CAPS_TIMEOUT); }
private void ParcelVoiceInfoResponse(CapsClient client, OSD response, Exception error) { if (response is OSDMap) { OSDMap respTable = (OSDMap)response; string regionName = respTable["region_name"].AsString(); int localID = (int)respTable["parcel_local_id"].AsInteger(); string channelURI = null; if (respTable["voice_credentials"] is OSDMap) { OSDMap creds = (OSDMap)respTable["voice_credentials"]; channelURI = creds["channel_uri"].AsString(); } if (OnParcelVoiceInfo != null) OnParcelVoiceInfo(regionName, localID, channelURI); } }
private void ProxyLoginSD(NetworkStream netStream, byte[] content) { lock (this) { AutoResetEvent remoteComplete = new AutoResetEvent(false); CapsClient loginRequest = new CapsClient(proxyConfig.remoteLoginUri); OSD response = null; loginRequest.OnComplete += new CapsClient.CompleteCallback( delegate(CapsClient client, OSD result, Exception error) { if (error == null) { if (result != null && result.Type == OSDType.Map) { response = result; } } remoteComplete.Set(); } ); loginRequest.BeginGetResponse(content, "application/llsd+xml", 1000 * 100); remoteComplete.WaitOne(1000 * 100, false); if (response == null) { byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 500 Internal Server Error\r\nContent-Length: 0\r\n\r\n"); netStream.Write(wr, 0, wr.Length); return; } OSDMap map = (OSDMap)response; OSD llsd; string sim_port = null, sim_ip = null, seed_capability = null; map.TryGetValue("sim_port", out llsd); if (llsd != null) sim_port = llsd.AsString(); map.TryGetValue("sim_ip", out llsd); if (llsd != null) sim_ip = llsd.AsString(); map.TryGetValue("seed_capability", out llsd); if (llsd != null) seed_capability = llsd.AsString(); if (sim_port == null || sim_ip == null || seed_capability == null) { if (map != null) { OpenMetaverse.Logger.Log("Connection to server failed, returned LLSD error follows:\n" + map.ToString(), Helpers.LogLevel.Error); } byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 500 Internal Server Error\r\nContent-Length: 0\r\n\r\n"); netStream.Write(wr, 0, wr.Length); return; } IPEndPoint realSim = new IPEndPoint(IPAddress.Parse(sim_ip), Convert.ToUInt16(sim_port)); IPEndPoint fakeSim = ProxySim(realSim); map["sim_ip"] = OSD.FromString(fakeSim.Address.ToString()); map["sim_port"] = OSD.FromInteger(fakeSim.Port); activeCircuit = realSim; // start a new proxy session Reset(); CapInfo info = new CapInfo(seed_capability, activeCircuit, "SeedCapability"); info.AddDelegate(new CapsDelegate(FixupSeedCapsResponse)); KnownCaps[seed_capability] = info; map["seed_capability"] = OSD.FromString(loginURI + seed_capability); StreamWriter writer = new StreamWriter(netStream); writer.Write("HTTP/1.0 200 OK\r\n"); writer.Write("Content-type: application/xml+llsd\r\n"); writer.Write("\r\n"); writer.Write(OSDParser.SerializeLLSDXmlString(response)); writer.Close(); } }
private bool RequestVoiceInternal(string me, CapsClient.CompleteCallback callback, string capsName) { if (Enabled && Client.Network.Connected) { if (Client.Network.CurrentSim != null && Client.Network.CurrentSim.Caps != null) { Uri url = Client.Network.CurrentSim.Caps.CapabilityURI(capsName); if (url != null) { CapsClient request = new CapsClient(url); OSDMap body = new OSDMap(); request.OnComplete += new CapsClient.CompleteCallback(callback); request.BeginGetResponse(body, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); return true; } else { Logger.Log("VoiceManager." + me + "(): " + capsName + " capability is missing", Helpers.LogLevel.Info, Client); return false; } } } Logger.Log("VoiceManager.RequestVoiceInternal(): Voice system is currently disabled", Helpers.LogLevel.Info, Client); return false; }
/// <summary> /// Create an inventory item and upload asset data /// </summary> /// <param name="data">Asset data</param> /// <param name="name">Inventory item name</param> /// <param name="description">Inventory item description</param> /// <param name="assetType">Asset type</param> /// <param name="invType">Inventory type</param> /// <param name="folderID">Put newly created inventory in this folder</param> /// <param name="permissions">Permission of the newly created item /// (EveryoneMask, GroupMask, and NextOwnerMask of Permissions struct are supported)</param> /// <param name="callback">Delegate that will receive feedback on success or failure</param> public void RequestCreateItemFromAsset(byte[] data, string name, string description, AssetType assetType, InventoryType invType, UUID folderID, Permissions permissions, ItemCreatedFromAssetCallback callback) { if (Client.Network.CurrentSim == null || Client.Network.CurrentSim.Caps == null) throw new Exception("NewFileAgentInventory capability is not currently available"); Uri url = Client.Network.CurrentSim.Caps.CapabilityURI("NewFileAgentInventory"); if (url != null) { OSDMap query = new OSDMap(); query.Add("folder_id", OSD.FromUUID(folderID)); query.Add("asset_type", OSD.FromString(Utils.AssetTypeToString(assetType))); query.Add("inventory_type", OSD.FromString(Utils.InventoryTypeToString(invType))); query.Add("name", OSD.FromString(name)); query.Add("description", OSD.FromString(description)); query.Add("everyone_mask", OSD.FromInteger((int)permissions.EveryoneMask)); query.Add("group_mask", OSD.FromInteger((int)permissions.GroupMask)); query.Add("next_owner_mask", OSD.FromInteger((int)permissions.NextOwnerMask)); query.Add("expected_upload_cost", OSD.FromInteger(Client.Settings.UPLOAD_COST)); // Make the request CapsClient request = new CapsClient(url); request.OnComplete += CreateItemFromAssetResponse; request.UserData = new object[] { callback, data, Client.Settings.CAPS_TIMEOUT, query }; request.BeginGetResponse(query, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT); } else { throw new Exception("NewFileAgentInventory capability is not currently available"); } }