public void Research(ulong key) { if (!Network.Responsive) { return; } // limit re-search to once per 30 secs DateTime timeout = default(DateTime); if (NextResearch.TryGetValue(key, out timeout)) { if (Core.TimeNow < timeout) { return; } } uint version = 0; OpVersionedFile file = GetFile(key); if (file != null) { version = file.Header.Version + 1; } StartSearch(key, version); NextResearch[key] = Core.TimeNow.AddSeconds(3); }
void LocalSync_TagReceived(ulong user, byte[] tag) { if (tag.Length == 0) { return; } uint version = 0; OpVersionedFile file = GetFile(user); if (file != null) { version = CompactNum.ToUInt32(tag, 0, tag.Length); // version old, so we need the latest localSync file // wont cause loop because localsync's fileAquired will only fire on new version of localSync if (version < file.Header.Version) { Core.Sync.Research(user); } } // if newer file on network, or this node is in our cache area, find it if ((file != null && version > file.Header.Version) || (file == null && ((!GlobalIM && Network.Routing.InCacheArea(user)) || (GlobalIM && Core.Buddies.BuddyList.SafeContainsKey(user))))) { StartSearch(user, version); // this could be called from a patch given to another user, direct connect not gauranteed } }
private void Process_VersionedFile(DataReq data, SignedData signed, VersionedFileHeader header) { Core.IndexKey(header.KeyID, ref header.Key); OpVersionedFile current = GetFile(header.KeyID); // if link loaded if (current != null) { // lower version if (header.Version < current.Header.Version) { if (data != null && data.Source != null) { Store.Send_StoreReq(data.Source, data.LocalProxy, new DataReq(null, current.UserID, Service, DataType, current.SignedHeader)); } return; } // higher version else if (header.Version > current.Header.Version) { CacheFile(signed, header); } } // else load file, set new header after file loaded else { CacheFile(signed, header); } }
public OpVersionedFile GetFile(ulong id) { OpVersionedFile vfile = null; FileMap.SafeTryGetValue(id, out vfile); return(vfile); }
void Cache_FileRemoved(OpVersionedFile file) { if (InRange.ContainsKey(file.UserID)) { InRange.Remove(file.UserID); } if (OutofRange.ContainsKey(file.UserID)) { OutofRange.Remove(file.UserID); } }
void Search_Local(ulong key, byte[] parameters, List <byte[]> results) { uint minVersion = BitConverter.ToUInt32(parameters, 0); OpVersionedFile vfile = GetFile(key); if (vfile != null) { if (vfile.Header.Version >= minVersion) { results.Add(vfile.SignedHeader); } } }
bool Transfers_FileSearch(ulong key, FileDetails details) { OpVersionedFile vfile = GetFile(key); if (vfile != null) { if (details.Size == vfile.Header.FileSize && Utilities.MemCompare(details.Hash, vfile.Header.FileHash)) { return(true); } } return(false); }
string Transfers_FileRequest(ulong key, FileDetails details) { OpVersionedFile vfile = GetFile(key); if (vfile != null) { if (details.Size == vfile.Header.FileSize && Utilities.MemCompare(details.Hash, vfile.Header.FileHash)) { return(GetFilePath(vfile.Header)); } } return(null); }
void Store_Patch(DhtAddress source, byte[] data) { if (data.Length < 9) { return; } ulong user = BitConverter.ToUInt64(data, 0); if (!Network.Routing.InCacheArea(user)) { return; } uint version = CompactNum.ToUInt32(data, 8, data.Length - 8); OpVersionedFile vfile = GetFile(user); if (vfile != null && vfile.Header != null) { if (vfile.Header.Version > version) { Store.Send_StoreReq(source, null, new DataReq(null, vfile.UserID, Service, DataType, vfile.SignedHeader)); return; } vfile.Unique = false; // network has current or newer version if (vfile.Header.Version == version) { return; } // else our version is old, download below } if (Network.Established) { Network.Searches.SendDirectRequest(source, user, Service, DataType, BitConverter.GetBytes(version)); } else { DownloadLater[user] = version; } }
void Cache_FileAquired(OpVersionedFile file) { ServiceData data = ServiceData.Decode(file.Header.Extra); if (GlobalIM) // cant check here if in buddy list because on localSync load, buddy list is null { InRange[file.UserID] = data; } if (Network.Routing.InCacheArea(file.UserID)) { InRange[file.UserID] = data; } else { OutofRange[file.UserID] = data; } InvokeTags(file.UserID, data); }
void Locations_TagReceived(DhtAddress address, ulong user, byte[] tag) { // if user not cached, we only active search their info if in local cache area if (tag.Length == 0) { return; } uint version = 0; OpVersionedFile file = Cache.GetFile(user); if (file != null) { version = CompactNum.ToUInt32(tag, 0, tag.Length); if (version < file.Header.Version) { Store.Send_StoreReq(address, null, new DataReq(null, file.UserID, ServiceID, DataTypeSync, file.SignedHeader)); } } // get new version of local sync file if ((file != null && version > file.Header.Version) || (file == null && ((!GlobalIM && Network.Routing.InCacheArea(user)) || (GlobalIM && Core.Buddies.BuddyList.SafeContainsKey(user))))) { Cache.Research(user); } // ensure we have the lastest versions of the user's services if (file != null) { CheckTags(file.UserID); } }
private void Cache_FileAquired(OpVersionedFile file) { if (file.UserID != Network.Local.UserID) return; // only we can open the buddly list stored on the network byte[] key = Core.User.Settings.KeyPair.Decrypt(file.Header.FileKey, false); using (TaggedStream tagged = new TaggedStream(Cache.GetFilePath(file.Header), Network.Protocol)) using (IVCryptoStream crypto = IVCryptoStream.Load(tagged, key)) { BuddyList.SafeClear(); PacketStream stream = new PacketStream(crypto, Network.Protocol, FileAccess.Read); G2Header root = null; while (stream.ReadPacket(ref root)) if (root.Name == BuddyPacket.Buddy) { OpBuddy buddy = OpBuddy.Decode(root); ulong id = Utilities.KeytoID(buddy.Key); Core.IndexKey(id, ref buddy.Key); Core.IndexName(id, buddy.Name); if(buddy.Ignored) IgnoreList.SafeAdd(id, buddy); else BuddyList.SafeAdd(id, buddy); } } Core.RunInGuiThread(GuiUpdate); }
public OpTrust(OpVersionedFile file) { File = file; }
void Cache_FileRemoved(OpVersionedFile file) { OpTrust trust = GetTrust(file.UserID); if (trust == null) return; ProjectRoots.LockReading(delegate() { foreach (uint project in trust.Links.Keys) if(ProjectRoots.ContainsKey(project)) ProjectRoots[project].SafeRemove(trust.Links[project]); }); trust.Reset(); trust.Loaded = false; TrustMap.SafeRemove(file.UserID); // alert services/gui if (LinkUpdate != null) LinkUpdate.Invoke(trust); Core.RunInGuiThread(GuiUpdate, trust.UserID); }
private void Cache_FileAquired(OpVersionedFile cachefile) { try { // get link directly, even if in unloaded state we need the same reference OpTrust trust = null; TrustMap.SafeTryGetValue(cachefile.UserID, out trust); if (trust == null) { trust = new OpTrust(cachefile); TrustMap.SafeAdd(cachefile.UserID, trust); } else trust.File = cachefile; // clean roots, if link has loopID, remove loop node entirely, it will be recreated if needed later ProjectRoots.LockReading(delegate() { foreach (uint project in ProjectRoots.Keys) { OpLink link = trust.GetLink(project); if (link == null) continue; ThreadedList<OpLink> roots = ProjectRoots[project]; roots.SafeRemove(link); // remove loop node if (link.LoopRoot != null) roots.LockReading(delegate() { foreach (OpLink root in roots) if (root.UserID == link.LoopRoot.UserID) { roots.SafeRemove(root); // root is a loop node // remove associations with loop node foreach (OpLink downlink in root.Downlinks) downlink.LoopRoot = null; break; } }); } }); trust.Reset(); // load data from link file string inheritName = null; string inheritOp = null; Bitmap inheritIcon = null; byte[] inheritSplash = null; using (TaggedStream file = new TaggedStream(Cache.GetFilePath(cachefile.Header), Network.Protocol)) using (IVCryptoStream crypto = IVCryptoStream.Load(file, cachefile.Header.FileKey)) { PacketStream stream = new PacketStream(crypto, Network.Protocol, FileAccess.Read); G2Header packetRoot = null; while (stream.ReadPacket(ref packetRoot)) { if (packetRoot.Name == DataPacket.SignedData) { SignedData signed = SignedData.Decode(packetRoot); G2Header embedded = new G2Header(signed.Data); // figure out data contained if (G2Protocol.ReadPacket(embedded)) { if (embedded.Name == TrustPacket.ProjectData) { ProjectData project = ProjectData.Decode(embedded); Process_ProjectData(trust, signed, project); if (project.ID == 0) { inheritName = project.UserName; inheritOp = project.Name; } } else if (embedded.Name == TrustPacket.LinkData) Process_LinkData(trust, signed, LinkData.Decode(embedded)); } } else if (packetRoot.Name == TrustPacket.WebCache) Network.Cache.AddWebCache(WebCache.Decode(packetRoot)); else if (packetRoot.Name == TrustPacket.Icon) inheritIcon = IconPacket.Decode(packetRoot).OpIcon; else if (packetRoot.Name == TrustPacket.Splash) { LargeDataPacket splash = LargeDataPacket.Decode(packetRoot); if (splash.Size > 0) inheritSplash = LargeDataPacket.Read(splash, stream, TrustPacket.Splash); } } } // set new header trust.Loaded = true; // set as root if node has no uplinks foreach (OpLink link in trust.Links.Values) if (link.Uplink == null) AddRoot(link); // if uplink is unknown - process link data will search for the unknown parent // if loop created, create new loop node with unique ID, assign all nodes in loop the ID and add as downlinks foreach (OpLink link in trust.Links.Values) if (IsLooped(link)) { uint project = link.Project; OpLink loop = new OpTrust(project, (ulong)Core.RndGen.Next()).GetLink(project); loop.IsLoopRoot = true; List<ulong> uplinks = GetUnconfirmedUplinkIDs(trust.UserID, project); uplinks.Add(trust.UserID); foreach (ulong uplink in uplinks) { OpLink member = GetLink(uplink, project); if (member == null) continue; member.LoopRoot = loop; loop.Downlinks.Add(member); loop.Confirmed.Add(member.UserID); //needed for getlowers } AddRoot(loop); } trust.CheckRequestVersions(); if (LinkUpdate != null) LinkUpdate.Invoke(trust); if (Core.NewsWorthy(trust.UserID, 0, false)) Core.MakeNews(ServiceIDs.Trust, "Trust updated by " + Core.GetName(trust.UserID), trust.UserID, 0, true); // update subs if (Network.Established) { List<LocationData> locations = new List<LocationData>(); ProjectRoots.LockReading(delegate() { foreach (uint project in ProjectRoots.Keys) if (Core.UserID == trust.UserID || IsHigher(trust.UserID, project)) GetLocsBelow(Core.UserID, project, locations); }); Store.PublishDirect(locations, trust.UserID, ServiceID, 0, cachefile.SignedHeader); } // inherit local settings if(Core.UserID == trust.UserID) { if (inheritName != null) Core.User.Settings.UserName = inheritName; } // inherit settings from highest node, first node in loop if (IsInheritNode(trust.UserID)) { if (inheritOp != null) Core.User.Settings.Operation = inheritOp; if (inheritIcon != null) { Core.User.OpIcon = inheritIcon; Core.User.IconUpdate(); } if (inheritSplash != null) Core.User.OpSplash = (Bitmap)Bitmap.FromStream(new MemoryStream(inheritSplash)); else Core.User.OpSplash = null; } // update interface node Core.RunInGuiThread(GuiUpdate, trust.UserID); foreach (OpLink link in trust.Links.Values) foreach (OpLink downlink in link.Downlinks) Core.RunInGuiThread(GuiUpdate, downlink.UserID); } catch (Exception ex) { Network.UpdateLog("Link", "Error loading file " + ex.Message); } }
public OpStorage(OpVersionedFile file) { File = file; }
void Cache_FileRemoved(OpVersionedFile file) { if(InRange.ContainsKey(file.UserID)) InRange.Remove(file.UserID); if (OutofRange.ContainsKey(file.UserID)) OutofRange.Remove(file.UserID); }
void Cache_FileRemoved(OpVersionedFile file) { OpStorage storage = GetStorage(file.UserID); if(storage != null) UnloadHeaderFile(GetFilePath(storage), storage.File.Header.FileKey); StorageMap.SafeRemove(file.UserID); }
private void Cache_FileAquired(OpVersionedFile file) { OpPlan prevPlan = GetPlan(file.UserID, false); OpPlan newPlan = new OpPlan(file); PlanMap.SafeAdd(newPlan.UserID, newPlan); if (file.UserID == Core.UserID) LocalPlan = newPlan; if ((newPlan == LocalPlan) || (prevPlan != null && prevPlan.Loaded)) // if loaded, reload LoadPlan(newPlan.UserID); // update subs if (Network.Established) { List<LocationData> locations = new List<LocationData>(); Trust.ProjectRoots.LockReading(delegate() { foreach (uint project in Trust.ProjectRoots.Keys) if (newPlan.UserID == Core.UserID || Trust.IsHigher(newPlan.UserID, project)) Trust.GetLocsBelow(Core.UserID, project, locations); }); Store.PublishDirect(locations, newPlan.UserID, ServiceID, DataTypeFile, newPlan.File.SignedHeader); } // see if we need to update our own goal estimates if (newPlan.UserID != Core.UserID && LocalPlan != null) Trust.ProjectRoots.LockReading(delegate() { foreach (uint project in Trust.ProjectRoots.Keys) if (Trust.IsLower(Core.UserID, newPlan.UserID, project)) // updated plan must be lower than us to have an effect foreach (int ident in LocalPlan.GoalMap.Keys) { if (!newPlan.Loaded) LoadPlan(newPlan.UserID); // if updated plan part of the same goal ident, re-estimate our own goals, incorporating update's changes if (newPlan.GoalMap.ContainsKey(ident) || newPlan.ItemMap.ContainsKey(ident)) foreach (PlanGoal goal in LocalPlan.GoalMap[ident]) { int completed = 0, total = 0; GetEstimate(goal, ref completed, ref total); if (completed != goal.EstCompleted || total != goal.EstTotal) { goal.EstCompleted = completed; goal.EstTotal = total; if (RunSaveLocal == 0) // if countdown not started, start RunSaveLocal = SaveInterval; } } } }); Core.RunInGuiThread(PlanUpdate, newPlan); if (Core.NewsWorthy(newPlan.UserID, 0, false)) Core.MakeNews(ServiceIDs.Plan, "Plan updated by " + Core.GetName(newPlan.UserID), newPlan.UserID, 0, false); }
private void CacheFile(SignedData signedHeader, VersionedFileHeader header) { if (Core.InvokeRequired) { Debug.Assert(false); } try { // check if file exists string path = ""; if (header.FileHash != null) { path = GetFilePath(header); if (!File.Exists(path)) { Download(signedHeader, header); return; } } // get file OpVersionedFile prevFile = GetFile(header.KeyID); if (prevFile != null) { if (header.Version < prevFile.Header.Version) { return; // dont update with older version } } OpVersionedFile newFile = new OpVersionedFile(header.Key); // set new header newFile.Header = header; newFile.SignedHeader = signedHeader.Encode(Network.Protocol); newFile.Unique = !Network.Established; FileMap.SafeAdd(header.KeyID, newFile); RunSaveHeaders = true; if (FileAquired != null) { FileAquired.Invoke(newFile); } // delete old file - do after aquired event so invoked (storage) can perform clean up operation if (prevFile != null && prevFile.Header.FileHash != null) { string oldPath = GetFilePath(prevFile.Header); if (path != oldPath && File.Exists(oldPath)) { try { File.Delete(oldPath); } catch { } } } } catch (Exception ex) { Core.Network.UpdateLog("VersionedFile", "Error caching data " + ex.Message); } }
void Cache_FileAquired(OpVersionedFile file) { ServiceData data = ServiceData.Decode(file.Header.Extra); if(GlobalIM ) // cant check here if in buddy list because on localSync load, buddy list is null InRange[file.UserID] = data; if (Network.Routing.InCacheArea(file.UserID)) InRange[file.UserID] = data; else OutofRange[file.UserID] = data; InvokeTags(file.UserID, data); }
void Cache_FileRemoved(OpVersionedFile file) { OpPlan plan = GetPlan(file.UserID, false); if (plan == null) return; PlanMap.SafeRemove(file.UserID); }
void Cache_FileAquired(OpVersionedFile file) { // unload old file OpStorage prevStorage = GetStorage(file.UserID); if (prevStorage != null) { string oldPath = GetFilePath(prevStorage); UnloadHeaderFile(oldPath, prevStorage.File.Header.FileKey); } OpStorage newStorage = new OpStorage(file); StorageMap.SafeAdd(file.UserID, newStorage); LoadHeaderFile(GetFilePath(newStorage), newStorage, false, false); // record changes of higher nodes for auto-integration purposes Trust.ProjectRoots.LockReading(delegate() { foreach (uint project in Trust.ProjectRoots.Keys) { List<ulong> inheritIDs = Trust.GetAutoInheritIDs(Core.UserID, project); if (Core.UserID == newStorage.UserID || inheritIDs.Contains(newStorage.UserID)) // doesnt get called on startup because working not initialized before headers are loaded if (Working.ContainsKey(project)) { bool doSave = Working[project].RefreshHigherChanges(newStorage.UserID); if (!Loading && !SavingLocal) Working[project].AutoIntegrate(doSave); } } }); // update subs - this ensures file not propagated lower until we have it (prevents flood to original poster) if (Network.Established) { List<LocationData> locations = new List<LocationData>(); Trust.ProjectRoots.LockReading(delegate() { foreach (uint project in Trust.ProjectRoots.Keys) if (newStorage.UserID == Core.UserID || Trust.IsHigher(newStorage.UserID, project)) Trust.GetLocsBelow(Core.UserID, project, locations); }); Store.PublishDirect(locations, newStorage.UserID, ServiceID, FileTypeCache, file.SignedHeader); } if (StorageUpdate != null) Core.RunInGuiThread(StorageUpdate, newStorage); if (Core.NewsWorthy(newStorage.UserID, 0, false)) Core.MakeNews(ServiceIDs.Storage, "File System updated by " + Core.GetName(newStorage.UserID), newStorage.UserID, 0, false); }
byte[] Locations_GetTag() { OpVersionedFile file = Cache.GetFile(Core.UserID); return((file != null) ? CompactNum.GetBytes(file.Header.Version) : null); }
public OpVersionedFile UpdateLocal(string tempPath, byte[] key, byte[] extra) { OpVersionedFile vfile = null; if (Core.InvokeRequired) { // block until completed Core.RunInCoreBlocked(delegate() { vfile = UpdateLocal(tempPath, key, extra); }); return(vfile); } vfile = GetFile(Core.UserID); VersionedFileHeader header = null; if (vfile != null) { header = vfile.Header; } string oldFile = null; if (header != null && header.FileHash != null) { oldFile = GetFilePath(header); } if (header == null) { header = new VersionedFileHeader(); } header.Key = Core.User.Settings.KeyPublic; header.KeyID = Core.UserID; // set so keycheck works header.Version++; header.FileKey = key; header.Extra = extra; // finish building header if (key != null) { Utilities.HashTagFile(tempPath, Network.Protocol, ref header.FileHash, ref header.FileSize); // move file, overwrite if need be string finalPath = GetFilePath(header); File.Move(tempPath, finalPath); } CacheFile(new SignedData(Network.Protocol, Core.User.Settings.KeyPair, header), header); SaveHeaders(); if (oldFile != null && File.Exists(oldFile)) // delete after move to ensure a copy always exists (names different) { try { File.Delete(oldFile); } catch { } } vfile = GetFile(Core.UserID); if (!LocalSync) { Core.Sync.UpdateLocal(); // calls this same function for local sync which publishes } else if (GlobalIM) { Core.Locations.UpdateLocation(); } else if (Network.Established) { Store.PublishNetwork(Core.UserID, Service, DataType, vfile.SignedHeader); Core.Locations.UpdateLocation(); } else { vfile.Unique = true; // publish when connected } return(vfile); }
private void CacheFile(SignedData signedHeader, VersionedFileHeader header) { if (Core.InvokeRequired) Debug.Assert(false); try { // check if file exists string path = ""; if (header.FileHash != null) { path = GetFilePath(header); if (!File.Exists(path)) { Download(signedHeader, header); return; } } // get file OpVersionedFile prevFile = GetFile(header.KeyID); if (prevFile != null) if (header.Version < prevFile.Header.Version) return; // dont update with older version OpVersionedFile newFile = new OpVersionedFile(header.Key); // set new header newFile.Header = header; newFile.SignedHeader = signedHeader.Encode(Network.Protocol); newFile.Unique = !Network.Established; FileMap.SafeAdd(header.KeyID, newFile); RunSaveHeaders = true; if(FileAquired != null) FileAquired.Invoke(newFile); // delete old file - do after aquired event so invoked (storage) can perform clean up operation if (prevFile != null && prevFile.Header.FileHash != null) { string oldPath = GetFilePath(prevFile.Header); if (path != oldPath && File.Exists(oldPath)) try { File.Delete(oldPath); } catch { } } } catch (Exception ex) { Core.Network.UpdateLog("VersionedFile", "Error caching data " + ex.Message); } }
public bool Loaded; // true if blocks/goals loaded #endregion Fields #region Constructors public OpPlan(OpVersionedFile file) { File = file; }