private void handleHelloMessage(HelloMessage msg, IPAddress sender) { // see if the peers list contains a SyncPeer with the same hostname SyncPeer found = _peers.Find((peer) => { return(peer.Hostname == msg.hostname); }); if (found != null) { // we know about this peer, update its last seen time found.LastResponded = DateTime.Now; } else { // we don't know about this peer, add it SyncPeer newPeer = new SyncPeer(); newPeer.Port = msg.listenPort; newPeer.Hostname = msg.hostname; newPeer.Address = sender; newPeer.LastResponded = DateTime.Now; _peers.Add(newPeer); Debug.WriteLine("Added new peer " + msg.hostname); SyncPeerUpdatedEventHandler handler = OnSyncPeerUpdated; if (handler != null) { handler(this, new SyncPeerUpdatedEventArgs(found, SyncPeerUpdatedAction.Added)); } // send our hello message quickly (so the peer doesn't have to wait ~5 seconds to get our next hello) _udpAgent.HurrySendHello(); // request the peer's applist Debug.WriteLine("Sending RequestAppList to " + sender.ToString()); RequestAppListMessage sendMsg = new RequestAppListMessage(); _tcpAgent.SendMessage(sendMsg, sender); } }
private void handleGoodbyeMessage(GoodbyeMessage msg, IPAddress sender) { // see if we know about this peer SyncPeer _found = _peers.Find((peer) => { return(peer.Address.Equals(sender)); }); // if so, remove from our peer list if (_found != null) { removePeer(_found); } }
private void handleAppListMessage(AppListMessage msg, IPAddress sender) { SyncPeer found = _peers.Find((peer) => { return(peer.Address.Equals(sender)); }); if (found == null) { Debug.WriteLine("Received AppList from unknown peer " + sender.ToString()); } found.Apps = msg.availableApps; updateAvailableApps(); Debug.WriteLine(String.Format("{0} has {1} available apps", found.Hostname, found.Apps.Count)); SyncPeerUpdatedEventHandler handler = OnSyncPeerUpdated; if (handler != null) { handler(this, new SyncPeerUpdatedEventArgs(found, SyncPeerUpdatedAction.Updated)); } }
private void removePeer(SyncPeer peer) { // remove the peers Debug.WriteLine("Removing " + peer.Hostname + " from peers list"); if (_peers.Contains(peer)) { _peers.Remove(peer); } // update list of available apps (i.e. remove any that are no longer available) updateAvailableApps(); // notify listeners that the peers have been removed (need to do this after available apps has been updated) SyncPeerUpdatedEventHandler handler = OnSyncPeerUpdated; if (handler != null) { handler(this, new SyncPeerUpdatedEventArgs(peer, SyncPeerUpdatedAction.Removed)); } }
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); } }
public SyncPeerUpdatedEventArgs(SyncPeer peer, SyncPeerUpdatedAction action) { Peer = peer; Action = action; }
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)); } }