public bool AddOrUpdateMapTile(SceneInfo sceneInfo, Image mapTile) { if (m_assetClient == null) return false; int zoomLevel = 1; uint x = (uint)sceneInfo.MinPosition.X / 256u; uint y = (uint)sceneInfo.MinPosition.Y / 256u; byte[] pngData; using (MemoryStream stream = new MemoryStream()) { mapTile.Save(stream, System.Drawing.Imaging.ImageFormat.Png); pngData = stream.ToArray(); } Asset asset = new Asset { ContentType = "image/png", CreationDate = DateTime.UtcNow, CreatorID = sceneInfo.ID, Data = pngData, ID = TileNameToUUID(zoomLevel, x, y) }; // TODO: Create and store the other zoom levels return m_assetClient.StoreAsset(asset); }
void Assets_OnAssetReceived(AssetDownload transfer, Asset asset) { KeyValuePair<UUID, UUID> kvp; Agent agent; if (currentDownloads.TryGetValue(transfer.ID, out kvp)) { currentDownloads.Remove(transfer.ID); if (server.Agents.TryGetValue(kvp.Key, out agent)) { if (transfer.Success) { server.Assets.StoreAsset(asset); TransferToClient(asset, agent, kvp.Value); } else { Logger.Log("Request for missing asset " + transfer.AssetID.ToString(), Helpers.LogLevel.Warning); // Asset not found TransferInfoPacket response = new TransferInfoPacket(); response.TransferInfo = new TransferInfoPacket.TransferInfoBlock(); response.TransferInfo.TransferID = kvp.Value; response.TransferInfo.Params = new byte[20]; Buffer.BlockCopy(transfer.AssetID.GetBytes(), 0, response.TransferInfo.Params, 0, 16); Buffer.BlockCopy(Utils.IntToBytes((int)transfer.AssetType), 0, response.TransferInfo.Params, 16, 4); response.TransferInfo.ChannelType = (int)ChannelType.Asset; response.TransferInfo.Size = 0; response.TransferInfo.Status = (int)StatusCode.UnknownSource; response.TransferInfo.TargetType = (int)TargetType.Unknown; server.UDP.SendPacket(agent.Avatar.ID, response, PacketCategory.Asset); } } else { Logger.Log("Asset transfer finished for an untracked agent, ignoring", Helpers.LogLevel.Warning); } } else { Logger.Log("Asset transfer finished for an untracked download, ignoring", Helpers.LogLevel.Warning); } }
private void Assets_OnAssetReceived(AssetDownload transfer, Asset asset) { if (transfer.AssetID == AssetID) { if (transfer.Success) { try { File.WriteAllBytes(String.Format("{0}.{1}", AssetID, assetType.ToString().ToLower()), asset.AssetData); Success = true; } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, ex); } } DownloadHandle.Set(); } }
public bool StoreAsset(Asset asset) { Debug.Assert(asset.Data != null, "Cannot store an asset without data"); Debug.Assert(!String.IsNullOrEmpty(asset.ContentType), "Cannot store an asset without a ContentType"); bool storedInCache = false; if (asset.ID == UUID.Zero) asset.ID = UUID.Random(); // Run this asset through the incoming asset filter if (!m_simian.FilterAsset(asset)) { m_log.InfoFormat("Asset {0} ({1}, {2} bytes) was rejected", asset.ID, asset.ContentType, asset.Data.Length); return false; } #region Caching if (m_dataStore != null) { byte[] metadata = CreateMetadata(asset.CreatorID, asset.ContentType, asset.Local, asset.Temporary, asset.Data, asset.ExtraHeaders); m_dataStore.AddOrUpdateAsset(asset.ID, METADATA_MIME_TYPE, metadata, true); m_dataStore.AddOrUpdateAsset(asset.ID, asset.ContentType, asset.Data, true); storedInCache = true; } #endregion Caching // If this is a local asset we don't need to store it remotely if (asset.Local) { if (!storedInCache) m_log.Error("Cannot store asset " + asset.ID + " (" + asset.ContentType + ") without an IDataStore"); return storedInCache; } #region Remote Storage // Distinguish public and private assets bool isPublic = true; switch (asset.ContentType) { case "application/vnd.ll.callingcard": case "application/vnd.ll.gesture": case "application/vnd.ll.lslbyte": case "application/vnd.ll.lsltext": isPublic = false; break; } // Build the remote storage request List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>() { new MultipartForm.Parameter("AssetID", asset.ID.ToString()), new MultipartForm.Parameter("CreatorID", asset.CreatorID.ToString()), new MultipartForm.Parameter("Temporary", asset.Temporary ? "1" : "0"), new MultipartForm.Parameter("Public", isPublic ? "1" : "0"), new MultipartForm.File("Asset", asset.ID.ToString(), asset.ContentType, asset.Data) }; // Make the remote storage request string errorMessage = null; try { HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl); HttpWebResponse response = MultipartForm.Post(request, postParameters); using (Stream responseStream = response.GetResponseStream()) { string responseStr = null; try { responseStr = responseStream.GetStreamString(); OSD responseOSD = OSDParser.Deserialize(responseStr); if (responseOSD.Type == OSDType.Map) { OSDMap responseMap = (OSDMap)responseOSD; if (responseMap["Success"].AsBoolean()) return true; else errorMessage = "Upload failed: " + responseMap["Message"].AsString(); } else { errorMessage = "Response format was invalid:\n" + responseStr; } } catch (Exception ex) { if (!String.IsNullOrEmpty(responseStr)) errorMessage = "Failed to parse the response:\n" + responseStr; else errorMessage = "Failed to retrieve the response: " + ex.Message; } } } catch (WebException ex) { errorMessage = ex.Message; } #endregion Remote Storage m_log.WarnFormat("Failed to remotely store asset {0} ({1}): {2}", asset.ID, asset.ContentType, errorMessage); return false; }
private void Assets_OnAssetReceived(AssetDownload download, Asset asset) { lock (Wearables.Dictionary) { // Check if this is a wearable we were waiting on foreach (KeyValuePair<WearableType,WearableData> kvp in Wearables.Dictionary) { if (kvp.Value.Item.AssetUUID == download.AssetID) { // Make sure the download succeeded if (download.Success) { kvp.Value.Asset = (AssetWearable)asset; Logger.DebugLog("Downloaded wearable asset " + kvp.Value.Asset.Name, Client); if (!kvp.Value.Asset.Decode()) { Logger.Log("Failed to decode asset:" + Environment.NewLine + Utils.BytesToString(asset.AssetData), Helpers.LogLevel.Error, Client); } lock (AgentTextures) { foreach (KeyValuePair<AppearanceManager.TextureIndex, UUID> texture in kvp.Value.Asset.Textures) { if (texture.Value != DEFAULT_AVATAR_TEXTURE) // this texture is not meant to be displayed { Logger.DebugLog("Setting " + texture.Key + " to " + texture.Value, Client); AgentTextures[(int)texture.Key] = texture.Value; } } } } else { Logger.Log("Wearable " + kvp.Key + "(" + download.AssetID.ToString() + ") failed to download, " + download.Status.ToString(), Helpers.LogLevel.Warning, Client); } break; } } } if (AssetDownloads.Count > 0) { // Dowload the next wearable in line PendingAssetDownload pad = AssetDownloads.Dequeue(); Assets.RequestAsset(pad.Id, pad.Type, true); } else { // Everything is downloaded if (OnAgentWearables != null) { try { OnAgentWearables(); } catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } } WearablesDownloadedEvent.Set(); } }
private bool TryRemoteFetch(UUID id, out Asset asset) { asset = null; Uri url = new Uri(m_serverUrl + id); try { HttpWebRequest request = UntrustedHttpWebRequest.Create(url); using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (Stream responseStream = response.GetResponseStream()) { UUID creatorID; UUID.TryParse(response.Headers.GetOne("X-Asset-Creator-Id"), out creatorID); byte[] sha256 = Utils.HexStringToBytes(response.Headers.GetOne("ETag"), true); // TODO: Only put unrecognized headers in ExtraHeaders Dictionary<string, string> extraHeaders = new Dictionary<string, string>(response.Headers.Count); foreach (string key in response.Headers.AllKeys) extraHeaders[key] = response.Headers.GetOne(key); // Create the asset object asset = new Asset(); asset.ContentType = response.ContentType; asset.CreationDate = response.LastModified; asset.CreatorID = creatorID; asset.ExtraHeaders = extraHeaders; asset.ID = id; asset.Local = false; asset.SHA256 = sha256; asset.Temporary = false; // Grab the asset data from the response stream using (MemoryStream stream = new MemoryStream()) { responseStream.CopyTo(stream, Int32.MaxValue); asset.Data = stream.ToArray(); } } } // Cache store if (asset != null && m_dataStore != null) { byte[] metadata = CreateMetadata(asset.CreatorID, asset.ContentType, asset.Local, asset.Temporary, asset.Data, asset.ExtraHeaders); m_dataStore.AddOrUpdateAsset(asset.ID, METADATA_MIME_TYPE, metadata, true); m_dataStore.AddOrUpdateAsset(asset.ID, asset.ContentType, asset.Data, true); } } catch (Exception ex) { m_log.Warn("Asset GET from " + url + " failed: " + ex.Message); } return (asset != null); }
private bool TryLocalFetch(UUID assetID, string contentType, out Asset asset) { if (m_dataStore == null) { asset = null; return false; } byte[] data; if (m_dataStore.TryGetAsset(assetID, contentType, out data)) { // Fetched the asset. Now try to fetch the metadata byte[] metadata; if (m_dataStore.TryGetAsset(assetID, METADATA_MIME_TYPE, out metadata)) { asset = CreateAsset(assetID, contentType, metadata, data); return true; } else { m_log.Info("Metadata missing for local asset " + assetID + " (" + contentType + "), removing local asset"); RemoveAsset(assetID, contentType); } } asset = null; return false; }
private void SendTexture(IHttpRequest request, IHttpResponse response, Asset texture) { string range = request.Headers.GetOne("Range"); if (!String.IsNullOrEmpty(range)) { // Range request int start, end; if (TryParseRange(range, out start, out end)) { end = Utils.Clamp(end, 1, texture.Data.Length); start = Utils.Clamp(start, 0, end - 1); //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); if (end - start < texture.Data.Length) response.Status = System.Net.HttpStatusCode.PartialContent; response.ContentLength = end - start; response.ContentType = texture.ContentType; response.Body.Write(texture.Data, start, end - start); } else { m_log.Warn("Malformed Range header: " + range); response.Status = System.Net.HttpStatusCode.BadRequest; } } else { // Full content request response.ContentLength = texture.Data.Length; response.ContentType = texture.ContentType; response.Body.Write(texture.Data, 0, texture.Data.Length); } }
private void TransferDownload(LLAgent agent, UUID transferID, UUID assetID, AssetType type, Asset asset) { const int MAX_CHUNK_SIZE = 1000; string contentType = LLUtil.LLAssetTypeToContentType((int)type); if (contentType == asset.ContentType) { m_log.Debug(String.Format("Transferring asset {0} ({1})", asset.ID, asset.ContentType)); TransferInfoPacket response = new TransferInfoPacket(); response.TransferInfo = new TransferInfoPacket.TransferInfoBlock(); response.TransferInfo.TransferID = transferID; // Set the response channel type response.TransferInfo.ChannelType = (int)ChannelType.Asset; // Params response.TransferInfo.Params = new byte[20]; assetID.ToBytes(response.TransferInfo.Params, 0); Utils.IntToBytes((int)type, response.TransferInfo.Params, 16); response.TransferInfo.Size = asset.Data.Length; response.TransferInfo.Status = (int)StatusCode.OK; response.TransferInfo.TargetType = (int)TargetType.Unknown; // Doesn't seem to be used by the client m_udp.SendPacket(agent, response, ThrottleCategory.Asset, false); // Transfer system does not wait for ACKs, just sends all of the // packets for this transfer out int processedLength = 0; int packetNum = 0; while (processedLength < asset.Data.Length) { TransferPacketPacket transfer = new TransferPacketPacket(); transfer.TransferData.ChannelType = (int)ChannelType.Asset; transfer.TransferData.TransferID = transferID; transfer.TransferData.Packet = packetNum++; int chunkSize = Math.Min(asset.Data.Length - processedLength, MAX_CHUNK_SIZE); transfer.TransferData.Data = new byte[chunkSize]; Buffer.BlockCopy(asset.Data, processedLength, transfer.TransferData.Data, 0, chunkSize); processedLength += chunkSize; if (processedLength >= asset.Data.Length) transfer.TransferData.Status = (int)StatusCode.Done; else transfer.TransferData.Status = (int)StatusCode.OK; m_udp.SendPacket(agent, transfer, ThrottleCategory.Asset, false); } } else { m_log.WarnFormat("Request for asset {0} with type {1} does not match actual asset type {2}", assetID, type, asset.ContentType); TransferNotFound(agent, transferID, assetID, type); } }
private bool JPEG2000Handler(Asset asset) { string layerBoundariesHeader = GetLayerBoundariesHeader(asset.ID, asset.Data); if (layerBoundariesHeader == null) { m_log.Error("Rejecting invalid JPEG2000 texture asset, ID=" + asset.ID + ", CreatorID=" + asset.CreatorID); return false; } if (asset.ExtraHeaders == null) asset.ExtraHeaders = new Dictionary<string, string>(); asset.ExtraHeaders["X-JPEG2000-Layers"] = layerBoundariesHeader; int width, height; Color4 color = GetAverageColor(asset.ID, asset.Data, out width, out height); if (width != 0 && height != 0) { asset.ExtraHeaders["X-JPEG2000-RGBA"] = String.Format("{0},{1},{2},{3}", color.R, color.G, color.B, color.A); asset.ExtraHeaders["X-JPEG2000-Width"] = width.ToString(); asset.ExtraHeaders["X-JPEG2000-Height"] = height.ToString(); } return true; }
private void Assets_OnAssetReceived(AssetDownload asset, Asset blah) { lock (CurrentDownloads) { // see if we have this in our transfer list QueuedDownloadInfo r = CurrentDownloads.Find(delegate(QueuedDownloadInfo q) { return q.TransferID == asset.ID; }); if (r != null && r.TransferID == asset.ID) { if (asset.Success) { // create the directory to put this in Directory.CreateDirectory(Path.GetDirectoryName(r.FileName)); // write out the file File.WriteAllBytes(r.FileName, asset.AssetData); Logger.DebugLog(Name + " Wrote: " + r.FileName, Client); TextItemsTransferred++; } else { TextItemErrors++; Console.WriteLine("{0}: Download of asset {1} ({2}) failed with status {3}", Name, r.FileName, r.AssetID.ToString(), asset.Status.ToString()); } // remove the entry CurrentDownloads.Remove(r); } } }
void TransferToClient(Asset asset, Agent agent, UUID transferID) { Logger.Log(String.Format("Transferring asset {0} ({1})", asset.AssetID, asset.AssetType), Helpers.LogLevel.Info); TransferInfoPacket response = new TransferInfoPacket(); response.TransferInfo = new TransferInfoPacket.TransferInfoBlock(); response.TransferInfo.TransferID = transferID; response.TransferInfo.Params = new byte[20]; Buffer.BlockCopy(asset.AssetID.GetBytes(), 0, response.TransferInfo.Params, 0, 16); Buffer.BlockCopy(Utils.IntToBytes((int)asset.AssetType), 0, response.TransferInfo.Params, 16, 4); response.TransferInfo.ChannelType = (int)ChannelType.Asset; response.TransferInfo.Size = asset.AssetData.Length; response.TransferInfo.Status = (int)StatusCode.OK; response.TransferInfo.TargetType = (int)TargetType.Unknown; // Doesn't seem to be used by the client server.UDP.SendPacket(agent.Avatar.ID, response, PacketCategory.Asset); // Transfer system does not wait for ACKs, just sends all of the // packets for this transfer out const int MAX_CHUNK_SIZE = Settings.MAX_PACKET_SIZE - 100; int processedLength = 0; int packetNum = 0; while (processedLength < asset.AssetData.Length) { TransferPacketPacket transfer = new TransferPacketPacket(); transfer.TransferData.ChannelType = (int)ChannelType.Asset; transfer.TransferData.TransferID = transferID; transfer.TransferData.Packet = packetNum++; int chunkSize = Math.Min(asset.AssetData.Length - processedLength, MAX_CHUNK_SIZE); transfer.TransferData.Data = new byte[chunkSize]; Buffer.BlockCopy(asset.AssetData, processedLength, transfer.TransferData.Data, 0, chunkSize); processedLength += chunkSize; if (processedLength >= asset.AssetData.Length) transfer.TransferData.Status = (int)StatusCode.Done; else transfer.TransferData.Status = (int)StatusCode.OK; server.UDP.SendPacket(agent.Avatar.ID, transfer, PacketCategory.Asset); } }
private void SendMesh(IHttpRequest request, IHttpResponse response, Asset asset) { // TODO: Enable this again when we confirm the viewer is properly handling partial mesh content string range = null; //request.Headers.GetOne("Range"); if (!String.IsNullOrEmpty(range)) { // Range request int start, end; if (TryParseRange(range, out start, out end)) { end = Utils.Clamp(end, 1, asset.Data.Length - 1); start = Utils.Clamp(start, 0, end - 1); int len = end - start + 1; //m_log.Debug("Serving " + start + " to " + end + " of " + asset.Data.Length + " bytes for mesh " + asset.ID); if (len < asset.Data.Length) response.Status = System.Net.HttpStatusCode.PartialContent; response.ContentLength = len; response.ContentType = asset.ContentType; response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, asset.Data.Length)); response.Body.Write(asset.Data, start, len); } else { m_log.Warn("Malformed Range header: " + range); response.Status = System.Net.HttpStatusCode.BadRequest; } } else { // Full content request response.ContentLength = asset.Data.Length; response.ContentType = asset.ContentType; response.Body.Write(asset.Data, 0, asset.Data.Length); } }
public bool StoreAsset(string contentType, bool local, bool temporary, byte[] data, UUID creatorID, out UUID assetID) { assetID = UUID.Random(); Asset asset = new Asset { ContentType = contentType, CreationDate = DateTime.UtcNow, CreatorID = creatorID, Data = data, ID = assetID, Local = local, Temporary = temporary, }; return StoreAsset(asset); }
private void LoadDefaultAssets() { string executingDir = Util.ExecutingDirectory(); string defaultAssetPath = Path.Combine(executingDir, DEFAULT_ASSETS_PATH); try { if (Directory.Exists(defaultAssetPath)) { string[] assets = Directory.GetFiles(defaultAssetPath); for (int i = 0; i < assets.Length; i++) { string filename = assets[i]; byte[] data = File.ReadAllBytes(filename); UUID assetID = ParseUUIDFromFilename(filename); string contentType = m_simian.ExtensionToContentType(Path.GetExtension(filename).TrimStart('.')); byte[] sha256 = Utils.SHA256(data); Asset asset; // Check if we already have this asset stored if (TryGetAssetMetadata(assetID, contentType, out asset) && CompareBuffers(sha256, asset.SHA256)) continue; asset = new Asset { ID = assetID, ContentType = contentType, CreationDate = DateTime.UtcNow, CreatorID = UUID.Zero, Local = false, Temporary = false, SHA256 = sha256, Data = data }; StoreAsset(asset); } m_log.Info("Loaded " + assets.Length + " default assets into the local asset store"); } } catch (Exception ex) { m_log.Error("Error loading default asset set: " + ex.Message); } }
public bool TryGetAssetMetadata(UUID assetID, string contentType, out Asset asset) { byte[] metadata; if (m_dataStore.TryGetAsset(assetID, METADATA_MIME_TYPE, out metadata)) { asset = CreateAsset(assetID, contentType, metadata, null); return true; } asset = null; return false; }
public bool StoreAsset(Asset asset) { Debug.Assert(asset.Data != null, "Cannot store an asset without data"); Debug.Assert(!String.IsNullOrEmpty(asset.ContentType), "Cannot store an asset without a ContentType"); if (asset.ID == UUID.Zero) asset.ID = UUID.Random(); // Run this asset through the incoming asset filter if (!m_simian.FilterAsset(asset)) { m_log.InfoFormat("Asset {0} ({1}, {2} bytes) was rejected", asset.ID, asset.ContentType, asset.Data.Length); return false; } byte[] metadata = CreateMetadata(asset.CreatorID, asset.ContentType, asset.Local, asset.Temporary, asset.Data, asset.ExtraHeaders); if (asset.Temporary) { m_dataStore.AddOrUpdateAsset(asset.ID, METADATA_MIME_TYPE, metadata, true); return m_dataStore.AddOrUpdateAsset(asset.ID, asset.ContentType, asset.Data, true); } else { m_dataStore.AddOrUpdateAsset(asset.ID, METADATA_MIME_TYPE, metadata); return m_dataStore.AddOrUpdateAsset(asset.ID, asset.ContentType, asset.Data); } }
public bool TryGetAsset(UUID assetID, string contentType, out Asset asset) { if (TryLocalFetch(assetID, contentType, out asset)) return true; if (TryRemoteFetch(assetID, out asset)) return true; m_log.Debug("Failed to fetch asset " + assetID + " (" + contentType + ")"); return false; }
public bool TryGetAssetMetadata(UUID assetID, string contentType, out Asset asset) { asset = null; // Try a local metadata fetch if (m_dataStore != null) { byte[] metadata; if (m_dataStore.TryGetAsset(assetID, METADATA_MIME_TYPE, out metadata)) { asset = CreateAsset(assetID, contentType, metadata, null); return true; } } // Try a remote metadata fetch Uri url = new Uri(m_serverUrl + assetID); try { HttpWebRequest request = UntrustedHttpWebRequest.Create(url); request.Method = "HEAD"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (Stream responseStream = response.GetResponseStream()) { UUID creatorID; UUID.TryParse(response.Headers.GetOne("X-Asset-Creator-Id"), out creatorID); byte[] sha256 = Utils.HexStringToBytes(response.Headers.GetOne("ETag"), true); // TODO: Only put unrecognized headers in ExtraHeaders Dictionary<string, string> extraHeaders = new Dictionary<string, string>(response.Headers.Count); foreach (string key in response.Headers.AllKeys) extraHeaders[key] = response.Headers.GetOne(key); // Create the metadata object asset = new Asset(); asset.ContentType = response.ContentType; asset.CreationDate = response.LastModified; asset.CreatorID = creatorID; asset.ExtraHeaders = extraHeaders; asset.ID = assetID; asset.Local = false; asset.SHA256 = sha256; asset.Temporary = false; } } // Cache store if (asset != null && m_dataStore != null) { byte[] metadata = CreateMetadata(asset.CreatorID, asset.ContentType, asset.Local, asset.Temporary, asset.Data, asset.ExtraHeaders); m_dataStore.AddOrUpdateAsset(asset.ID, METADATA_MIME_TYPE, metadata, true); } } catch (Exception ex) { m_log.Warn("Asset HEAD from " + url + " failed: " + ex.Message); } return (asset != null); }
public UUID RequestUpload(Asset asset, bool storeLocal) { if (asset.AssetData == null) throw new ArgumentException("Can't upload an asset with no data (did you forget to call Encode?)"); UUID assetID; UUID transferID = RequestUpload(out assetID, asset.AssetType, asset.AssetData, storeLocal); asset.AssetID = assetID; return transferID; }
public bool TryGetCachedAsset(UUID assetID, string contentType, out Asset asset) { return TryLocalFetch(assetID, contentType, out asset); }
private Asset CreateAsset(AssetType type, UUID assetID, DateTime creationDate, UUID creatorID, bool local, bool temporary, byte[] data) { Asset asset = new Asset(); asset.ID = assetID; asset.ContentType = LLUtil.LLAssetTypeToContentType((int)type); asset.CreationDate = creationDate; asset.CreatorID = creatorID; asset.Data = data; asset.Local = local; asset.Temporary = temporary; //asset.SHA1 is filled in later return asset; }
private Asset CreateAsset(UUID assetID, string contentType, byte[] metadata, byte[] data) { Asset asset = new Asset { ID = assetID, ContentType = contentType, Data = data }; try { using (MemoryStream stream = new MemoryStream(metadata)) { OSDMap map = OSDParser.DeserializeJson(stream) as OSDMap; asset.Local = map["local"].AsBoolean(); asset.Temporary = map["temporary"].AsBoolean(); asset.CreationDate = map["creation_date"].AsDate(); asset.CreatorID = map["creator_id"].AsUUID(); asset.SHA256 = map["sha256"].AsBinary(); if (map.ContainsKey("extra_headers")) { OSDMap headerMap = map["extra_headers"] as OSDMap; asset.ExtraHeaders = new Dictionary<string, string>(headerMap.Count); foreach (KeyValuePair<string, OSD> kvp in headerMap) asset.ExtraHeaders.Add(kvp.Key, kvp.Value.AsString()); } return asset; } } catch (Exception ex) { m_log.Error("Failed to decode metadata for " + assetID + " (" + contentType + "): " + ex.Message); return null; } }
private void assetReceivedCallback(AssetDownload transfer, Asset asset) { if (OnAssetReceived != null) { OnAssetReceived(transfer, asset); } }
public QueueAsset(Transfer transfer, OpenMetaverse.Asset asset) { this.transfer = transfer; this.asset = asset; }