private void startReceiveApp(TransferInfo transfer, AppManifest existingFiles) { lock (Transfers) { Transfers.Add(transfer.TransferId, transfer); } subscribeTransferEvents(transfer); // create agent to handle the transfer TransferAgent agent = new TransferAgent(); agent.StartReceive(transfer); // fire event to notify listeners a transfer was created TransferCreatedEventHandler handler = OnTransferCreated; if (handler != null) { handler(this, new TransferEventArgs(transfer)); } // send the peer a request RequestAppTransferMessage newMsg = new RequestAppTransferMessage(); newMsg.appId = transfer.App.AppId; newMsg.transferId = transfer.TransferId; newMsg.listenPort = transfer.Port; if (existingFiles != null) { newMsg.existingFiles = existingFiles; } _tcpAgent.SendMessage(newMsg, transfer.Peer.Address); }
public void RemoveMatchingFiles(AppManifest otherManifest) { // build dictionary of files Dictionary <string, AppManifestFile> filesDict = new Dictionary <string, AppManifestFile>(); foreach (AppManifestFile thisFile in files) { filesDict.Add(thisFile.NormalizedPath, thisFile); } // see which ones exist foreach (AppManifestFile f in otherManifest.files) { if (filesDict.ContainsKey(f.NormalizedPath)) { if (filesDict[f.NormalizedPath].sha1_hash == f.sha1_hash) { // the other manifest contains a file with the same path and same hash, so remove our local copy files.Remove(filesDict[f.NormalizedPath]); } } else { // the other manifest contains a file that's not in our local manifest, so create it in our manifest // but with a filesize of zero to indicate that it should be deleted files.Add(new AppManifestFile(f.path, 0)); } } }
public static AppManifest FromDirectory(string path, bool hashFiles) { AppManifest manifest = new AppManifest(); manifest._hashFiles = hashFiles; DirectoryInfo di = new DirectoryInfo(path); try { manifest.AddDirectory(di, di); } catch (Exception e) { throw e; } return(manifest); }
public static AppManifest FromAppInfo(AppInfo app, AppLibrary library, bool hashFiles) { string libPath = library.Path; Utility.EnsureEndsWithSlash(ref libPath); DirectoryInfo di = new DirectoryInfo(libPath + AppManifest.STEAM_COMMON_DIR + app.InstallDir); AppManifest manifest = new AppManifest(); manifest._hashFiles = hashFiles; try { manifest.AddDirectory(di, di); } catch (Exception e) { throw e; } return(manifest); }
public void RequestApp(AppInfo app) { if (app == null) { throw new ArgumentNullException("Cannot request null app"); } if (app.InstallDir.Length == 0 || app.InstallDir.Contains(Path.DirectorySeparatorChar) || app.InstallDir.Contains(Path.AltDirectorySeparatorChar)) { throw new ArgumentOutOfRangeException("Cannot request app with invalid install dir [" + app.InstallDir + "]"); } // determine who has a copy of the app SyncPeer whoHasIt = null; foreach (SyncPeer peer in _peers) { if (peer.Apps.Contains(app)) { whoHasIt = peer; break; } } if (whoHasIt == null) { throw new AppNotAvailableException(); } // determine install dir string manifestRoot = Library.Path; Utility.EnsureEndsWithSlash(ref manifestRoot); manifestRoot += AppManifest.STEAM_COMMON_DIR + app.InstallDir; Utility.EnsureEndsWithSlash(ref manifestRoot); DirectoryInfo diManifest = new DirectoryInfo(manifestRoot); AppManifest existingFiles = null; if (!diManifest.Exists) { diManifest.Create(); } else { // determine which files we already have for this app, // and send that as part of the request message // todo - build manifest async existingFiles = AppManifest.FromDirectory(diManifest.FullName, true); } // create a transfer TransferInfo transfer = new TransferInfo(); // generates a transferid transfer.IsSending = false; transfer.Peer = whoHasIt; transfer.App = app; transfer.Port = Properties.Settings.Default.ListenPort; transfer.ManifestRoot = diManifest; if (getReceiveTransfersInProgress() == 0) { // start immediately if we're not receiving anything else Debug.WriteLine("Starting transfer agent to receive " + transfer.App.Name); startReceiveApp(transfer, existingFiles); } else { // otherwise add to the queue Debug.WriteLine("Queuing transfer of " + transfer.App.Name); TransferQueue.Enqueue(transfer); } }
private void handleRequestAppTransferMessage(RequestAppTransferMessage msg, IPAddress sender) { // see if we have the app AppInfo theApp = Library.Apps[msg.appId]; if (theApp == null) { Debug.WriteLine(String.Format("{1} requested AppId {0} but I don't have it", msg.appId, sender.ToString())); return; } // find the peer SyncPeer peer = _peers.Find((aPeer) => { return(aPeer.Address.Equals(sender)); }); Debug.WriteLine(String.Format("I will transfer {0} to {1}", msg.appId, peer.Hostname)); bool isUpdateRequest = msg.existingFiles != null; // build manifest AppManifest manifest = AppManifest.FromAppInfo(theApp, Library, isUpdateRequest); // todo - async/threaded // if peer provided a list of existing files, check our own if (isUpdateRequest) { manifest.RemoveMatchingFiles(msg.existingFiles); } // verify manifest is valid if (manifest == null) { Debug.WriteLine("Could not build manifest for AppId [" + msg.appId + "], aborting."); CancelAppTransferMessage cancelMsg = new CancelAppTransferMessage(); cancelMsg.transferId = msg.transferId; cancelMsg.reason = "Unable to build manifest"; _tcpAgent.SendMessage(cancelMsg, sender); return; } // send "start transfer" message with manifest StartAppTransferMessage newMsg = new StartAppTransferMessage(); newMsg.manifest = manifest; newMsg.transferId = msg.transferId; _tcpAgent.SendMessage(newMsg, sender); // create transfer TransferInfo transfer = new TransferInfo(newMsg.transferId); transfer.Manifest = newMsg.manifest; transfer.App = theApp; transfer.IsSending = true; transfer.Peer = peer; transfer.Port = msg.listenPort; // determine install dir and write string manifestRoot = Library.Path; Utility.EnsureEndsWithSlash(ref manifestRoot); manifestRoot += AppManifest.STEAM_COMMON_DIR + theApp.InstallDir; // todo ensure no path chars in installdir Utility.EnsureEndsWithSlash(ref manifestRoot); DirectoryInfo diManifest = new DirectoryInfo(manifestRoot); if (!diManifest.Exists) { diManifest.Create(); } transfer.ManifestRoot = diManifest; // subscribe to state change notifications (so we can update our status message) subscribeTransferEvents(transfer); // create agent to send the files TransferAgent agent = new TransferAgent(); agent.StartSend(transfer); // fire event to notify listeners a transfer was created TransferCreatedEventHandler handler = OnTransferCreated; if (handler != null) { handler(this, new TransferEventArgs(transfer)); } }