/// <summary> /// /// </summary> /// <param name="Msg"></param> private void RequestRecieved(NetConnection Client, NetMessage_RequestRemoteAction Msg) { RemoteActionServerState State = AllocateState(Msg.ActionId, Msg.Type); State.Settings = Msg.Settings; State.ForClient = Client; State.Progress = 0.0f; State.ProgressText = "Waiting for available client ..."; State.Dirty = true; }
/// <summary> /// /// </summary> /// <param name="Msg"></param> private void RequestRecieved(NetMessage_RequestRemoteAction Msg) { Logger.Log(LogLevel.Info, LogCategory.Main, "Server is requesting us to start a remote action '{0}'.", Msg.Id.ToString()); RemoteActionClientState State = AllocateState(Msg.Type); State.Id = Msg.ActionId; State.RemoteInitiated = true; State.Settings = Msg.Settings; State.Work = Task.Run(() => { RunAction(State, State.WorkTokenSource.Token); }, State.WorkTokenSource.Token); }
/// <summary> /// /// </summary> /// <param name="ManifestId"></param> /// <param name="DeviceName"></param> /// <param name="DeviceLocation"></param> /// <returns></returns> public Guid RequestRemoteInstall(Guid ManifestId, string DeviceName, string InstallLocation) { if (!Client.Connection.IsReadyForData) { Logger.Log(LogLevel.Info, LogCategory.Main, "Failed to start remote install. No connection."); return(Guid.Empty); } RemoteActionClientState State = AllocateState(RemoteActionType.Install); NetMessage_RequestRemoteAction Msg = new NetMessage_RequestRemoteAction(); Msg.ActionId = State.Id; Msg.Type = RemoteActionType.Install; Msg.Settings["ManifestId"] = ManifestId.ToString(); Msg.Settings["DeviceName"] = DeviceName; Msg.Settings["InstallLocation"] = InstallLocation; Client.Connection.Send(Msg); return(State.Id); }
/// <summary> /// /// </summary> /// <returns></returns> public void Poll() { for (int i = 0; i < States.Count; i++) { RemoteActionServerState State = States[i]; // If this action has been allocated a client, wait for result. if (State.AllocatedClient != null) { // Client has not updated us in quite a while :( if (TimeUtils.Ticks - State.LastUpdateRecieved > RemoteActionServerState.LastUpdateTimeout) { Logger.Log(LogLevel.Info, LogCategory.Main, "Remote action '{0}' failed as no response has been heard from allocated client.", State.Id.ToString()); State.ResultMessage = "Remote client failed to send update in time."; State.Completed = true; State.Failed = true; State.Dirty = true; } // Client who was allocated this action has disconnected, so abort. else if (!State.AllocatedClient.IsConnected) { Logger.Log(LogLevel.Info, LogCategory.Main, "Remote action '{0}' failed as allocated client disconnected.", State.Id.ToString()); State.ResultMessage = "Remote client unexpected disconnected."; State.Completed = true; State.Failed = true; State.Dirty = true; } } // Otherwise send out a solicitation to perform action. else { // Client who requested this action has disconnected, so abort. if (!State.ForClient.IsConnected) { Logger.Log(LogLevel.Info, LogCategory.Main, "Remote action '{0}' failed as requesting client disconnected.", State.Id.ToString()); State.ResultMessage = "Requesting client unexpected disconnected."; State.Completed = true; State.Failed = true; State.Dirty = true; } // Client has cancelled this state. else if (State.Cancelled) { Logger.Log(LogLevel.Info, LogCategory.Main, "Remote action '{0}' failed as client cancelled it.", State.Id.ToString()); State.ResultMessage = "Cancelled by user."; State.Completed = true; State.Failed = true; State.Dirty = true; // Tell client allocated the job to cancel. if (State.AllocatedClient != null && State.AllocatedClient.IsConnected) { NetMessage_CancelRemoteAction Msg = new NetMessage_CancelRemoteAction(); Msg.ActionId = State.Id; State.AllocatedClient.Send(Msg); } } // Send new solicitation. else if (TimeUtils.Ticks - State.LastSolicitBroadcast > RemoteActionServerState.SolicitInterval) { Logger.Log(LogLevel.Info, LogCategory.Main, "Remote action '{0}' sending new solicitation request.", State.Id.ToString()); List <NetConnection> Clients = Server.ListenConnection.AllClients; foreach (NetConnection ClientConnection in Clients) { if (ClientConnection != State.ForClient && ClientConnection.Metadata != null) { ServerConnectedClient ClientState = ClientConnection.Metadata as ServerConnectedClient; if (ClientState.AllowRemoteActions) { NetMessage_SolicitRemoteAction Msg = new NetMessage_SolicitRemoteAction(); Msg.ActionId = State.Id; Msg.Type = State.Type; Msg.Settings = State.Settings; ClientConnection.Send(Msg); } } } State.LastSolicitBroadcast = TimeUtils.Ticks; } // Nobody responded saying they can perform the action :| else if (TimeUtils.Ticks - State.RecievedTime > RemoteActionServerState.SolicitTimeout) { Logger.Log(LogLevel.Info, LogCategory.Main, "Remote action '{0}' failed as nobody responded to solicitation.", State.Id.ToString()); State.ResultMessage = "No remote clients accepted request."; State.Completed = true; State.Failed = true; State.Dirty = true; } // We have a client who can do the job! else if (State.SolicitationReplies.Count > 0 && TimeUtils.Ticks - State.LastSolicitBroadcast > RemoteActionServerState.MinSolicitWait) { Logger.Log(LogLevel.Info, LogCategory.Main, "Remote action '{0}' recieved solicitation reply and is starting.", State.Id.ToString()); State.AllocatedClient = State.SolicitationReplies[SolicitSelectionRandom.Next(0, State.SolicitationReplies.Count - 1)]; State.SolicitationReplies.Clear(); State.LastUpdateRecieved = TimeUtils.Ticks; NetMessage_RequestRemoteAction Msg = new NetMessage_RequestRemoteAction(); Msg.ActionId = State.Id; Msg.Type = State.Type; Msg.Settings = State.Settings; State.AllocatedClient.Send(Msg); } } // Send progress update to the client. if (TimeUtils.Ticks - State.LastUpdateSent > RemoteActionServerState.UpdateInterval || State.Dirty) { if (State.ForClient.IsConnected) { if (State.Completed || TimeUtils.Ticks - State.LastUpdateSent > RemoteActionClientState.MinUpdateInterval) { NetMessage_RemoteActionProgress Msg = new NetMessage_RemoteActionProgress(); Msg.ActionId = State.Id; Msg.Completed = State.Completed; Msg.Failed = State.Failed; Msg.ResultMessage = State.ResultMessage; Msg.Progress = State.Progress; Msg.ProgressText = State.ProgressText; State.ForClient.Send(Msg); State.LastUpdateSent = TimeUtils.Ticks; } } State.Dirty = false; // If completed, clean up state. if (State.Completed) { RemoveActionState(State.Id); } } } }