public void RemoveActivity(ActivityInformation activityInformation) { if (!allProcessingActivies.Remove(activityInformation.activityID)) { Debug.LogError("Remove Activity Failed."); } }
/// <summary> /// Copies values from signed activity information to properties of this instance of the activity. /// </summary> /// <param name="SignedActivity">Signed description of the activity.</param> /// <param name="PrimaryServerId">In case of NeighborActivity, this is identifier of the primary proximity server of the activity.</param> public void CopyFromSignedActivityInformation(SignedActivityInformation SignedActivity, byte[] PrimaryServerId = null) { ActivityInformation activity = SignedActivity.Activity; GpsLocation activityLocation = new GpsLocation(activity.Latitude, activity.Longitude); byte[] pubKey = activity.OwnerPublicKey.ToByteArray(); byte[] identityId = Crypto.Sha256(pubKey); this.Version = new SemVer(activity.Version).ToByteArray(); this.ActivityId = activity.Id; this.OwnerIdentityId = identityId; this.OwnerPublicKey = pubKey; this.OwnerProfileServerId = activity.ProfileServerContact.NetworkId.ToByteArray(); this.OwnerProfileServerIpAddress = activity.ProfileServerContact.IpAddress.ToByteArray(); this.OwnerProfileServerPrimaryPort = (ushort)activity.ProfileServerContact.PrimaryPort; this.Type = activity.Type; this.LocationLatitude = activityLocation.Latitude; this.LocationLongitude = activityLocation.Longitude; this.PrecisionRadius = activity.Precision; this.StartTime = ProtocolHelper.UnixTimestampMsToDateTime(activity.StartTime).Value; this.ExpirationTime = ProtocolHelper.UnixTimestampMsToDateTime(activity.ExpirationTime).Value; this.Signature = SignedActivity.Signature.ToByteArray(); this.ExtraData = activity.ExtraData; if (this is NeighborActivity) { (this as NeighborActivity).PrimaryServerId = PrimaryServerId; } }
public void OnActivityAssigned(ActivityInformation activityInformation) { switch (activityInformation.activityType) { case ActivityType.Quest: { GameObject ActivityTimerGO = new GameObject(activityInformation.activityID.ToString()); ActivityTimerGO.transform.SetParent(NotificationManager.Instance.gameObject.transform.Find("ActivitiesList")); ClockTimer questTimer = ActivityTimerGO.AddComponent <ClockTimer>(); questTimer.activityInformation = activityInformation; break; } case ActivityType.Craft: { GameObject ActivityTimerGO = new GameObject(activityInformation.activityID.ToString()); ActivityTimerGO.transform.SetParent(NotificationManager.Instance.gameObject.transform.Find("ActivitiesList")); PointTimer craftTimer = ActivityTimerGO.AddComponent <PointTimer>(); craftTimer.activityInformation = (activityInformation); break; } case ActivityType.Build: { Builder builder = BuildingManager.Instance.AllBuildings.SingleOrDefault(b => b.ID == activityInformation.informationID); builder.representGameObject.GetComponent <BuildTimer>().activityInformation = activityInformation; Debug.Log($"{builder.representGameObject.GetComponent<BuildTimer>().activityInformation.activityID}"); break; } case ActivityType.Pregnancy: { GameObject ActivityTimerGO = new GameObject(activityInformation.activityID.ToString()); ActivityTimerGO.transform.SetParent(NotificationManager.Instance.gameObject.transform.Find("ActivitiesList")); ClockTimer questTimer = ActivityTimerGO.AddComponent <ClockTimer>(); questTimer.activityInformation = activityInformation; break; } case ActivityType.CharacterGrowing: { GameObject ActivityTimerGO = new GameObject(activityInformation.activityID.ToString()); ActivityTimerGO.transform.SetParent(NotificationManager.Instance.gameObject.transform.Find("ActivitiesList")); ClockTimer questTimer = ActivityTimerGO.AddComponent <ClockTimer>(); questTimer.activityInformation = activityInformation; break; } default: { Debug.LogWarning($"{activityInformation.activityType} is currently unhandled."); break; } } }
/// <summary> /// Creates a new instance of activity information from the activity. /// </summary> /// <returns>New instance of the ActivityInformation structure.</returns> public ActivityInformation ToActivityInformation() { GpsLocation activityLocation = this.GetLocation(); ActivityInformation res = new ActivityInformation() { Version = new SemVer(this.Version).ToByteString(), Id = this.ActivityId, OwnerPublicKey = ProtocolHelper.ByteArrayToByteString(this.OwnerPublicKey), ProfileServerContact = new ServerContactInfo() { IpAddress = ProtocolHelper.ByteArrayToByteString(this.OwnerProfileServerIpAddress), NetworkId = ProtocolHelper.ByteArrayToByteString(this.OwnerProfileServerId), PrimaryPort = this.OwnerProfileServerPrimaryPort, }, Type = this.Type != null ? this.Type : "", Latitude = activityLocation.GetLocationTypeLatitude(), Longitude = activityLocation.GetLocationTypeLongitude(), Precision = this.PrecisionRadius, StartTime = ProtocolHelper.DateTimeToUnixTimestampMs(this.StartTime), ExpirationTime = ProtocolHelper.DateTimeToUnixTimestampMs(this.ExpirationTime), ExtraData = this.ExtraData != null ? this.ExtraData : "" }; return(res); }
void OnActivityFinished(ActivityInformation activityInformation) { if (activityInformation.activityType == ActivityType.Build) { RefreshProductionAmount(); } }
void OnActivityFinished(ActivityInformation activity) { if (activity.activityType == ActivityType.Build) { RefreshInformationCanvas(); } }
public void ChangeSpeedUpCost(ActivityInformation activity, int cost) { if (gameObject.activeSelf) { Text text = transform.Find("ScrollPanel/Container/" + activity.activityID + "/SpeedUpButton/Text").GetComponent <Text>(); text.text = $"<color=blue>{cost}</color> D"; } }
public void CancelMobileNotification(ActivityInformation activityInformation) { if (activityInformation == null) { return; } #if UNITY_ANDROID AndroidNotificationCenter.CancelScheduledNotification(activityInformation.androidNotificationID); #endif }
/// <summary> /// The business logic to process the import is written here /// </summary> /// <param name="data">The input byte[] to be processed</param> /// <returns>An instance of ActivityDataResponse</returns> public override async Task <ActivityDataResponse> Import(byte[] data) { try { var content = Encoding.Default.GetString(data); List <string> invalidData; List <CalendarChart> calendarCharts = _scheduleService.ParseCalenderCharts(content, out invalidData, true); if (calendarCharts.Any()) { ActivityInformation activityInformation = new ActivityInformation { Origin = ActivityOrigin.EStart, Status = ActivityStatus.Updated, Type = ActivityType.SchedulingmanagerGrid }; List <ScheduleManagerDetails> scheduleManagerDetailsList = await _scheduleService.GenerateAgentScheduleManagerCharts(calendarCharts, activityInformation); var agentScheduleManagers = _mapper.Map <List <AgentScheduleManager> >(scheduleManagerDetailsList).ToList(); _agentScheduleManagerRepository.UpsertAgentScheduleManagers(agentScheduleManagers); var activityLogs = _mapper.Map <List <ActivityLog> >(scheduleManagerDetailsList).ToList(); _activityLogRepository.CreateActivityLogs(activityLogs); await _uow.Commit(); } if (invalidData.Any()) { return(new ActivityDataResponse() { Status = (int)ProcessStatus.Partial, Metadata = string.Join("\r\n", invalidData) }); } return(new ActivityDataResponse() { Status = (int)ProcessStatus.Success }); } catch (Exception ex) { return(new ActivityDataResponse() { Status = (int)ProcessStatus.Failed, Metadata = ex.Message + "at - \n\n" + ex.StackTrace }); } }
public void UpdateMobileNotification(ActivityInformation activityInformation) { #if UNITY_ANDROID AndroidNotification androidNotification = new AndroidNotification() { Title = activityInformation.activityName, Text = $"{activityInformation.activityName} is already finished !", FireTime = new DateTime(activityInformation.finishTime), // ShouldAutoCancel = true }; Debug.Log($"Update noti {activityInformation.activityName} to {new DateTime(activityInformation.finishTime)}"); AndroidNotificationCenter.UpdateScheduledNotification(activityInformation.androidNotificationID, androidNotification, "Channel1"); #endif }
protected override void OnActivityAssigned(ActivityInformation activityInformation) { base.OnActivityAssigned(activityInformation); if (slider != null) { long timer = ((finishTime - activityInformation.startPoint) / TimeSpan.TicksPerSecond) - (((finishTime - activityInformation.startPoint) - timeLeft) / TimeSpan.TicksPerSecond); int hours = Mathf.FloorToInt(timer / 3600); int minutes = Mathf.FloorToInt(timer % 3600 / 60); int seconds = Mathf.FloorToInt(timer % 3600 % 60f); slider.GetComponentInChildren <Text>().text = String.Format("{0:00}:{1:00}:{2:00}", hours, minutes, seconds); } }
public void AddActivity(ActivityInformation activityInformation) { if (!LoadManager.Instance.playerData.completeTutorial) { return; } activityInformation.activityID = GetActivityID(); allProcessingActivies.Add(activityInformation.activityID, activityInformation); StartCoroutine(SetMobileNotificationSchedule(activityInformation)); EventManager.Instance.ActivityAssigned(activityInformation); }
IEnumerator SetMobileNotificationSchedule(ActivityInformation activityInformation) { yield return(new WaitForEndOfFrame()); yield return(new WaitForEndOfFrame()); #if UNITY_ANDROID Debug.Log($"{activityInformation.activityName} Notification in {new DateTime(activityInformation.finishTime)} : {activityInformation.finishTime}"); AndroidNotification androidNotification = new AndroidNotification() { Title = activityInformation.activityName, Text = $"{activityInformation.activityName} is already finished !", FireTime = new DateTime(activityInformation.finishTime), // ShouldAutoCancel = true }; activityInformation.androidNotificationID = AndroidNotificationCenter.SendNotification(androidNotification, "Channel1"); #endif }
//ตอนกดตอนสุดท้ายที่นับเวลาเสร็จ public void FinishQuest(ActivityInformation quest) { // Debug.Log(quest.activityID); //ดึงข้อมูลเควสมา QuestData questData = LoadManager.Instance.allQuestData[quest.informationID]; //สร้างลิส เก็บคาร์ทุกตัวในทีมที่ทำเควสนี้ List <Character> characters = new List <Character>(); characters.AddRange(townBase.CharacterInBuilding[quest.teamNumber].Characters); //เปลี่ยนสถานะลับเป็นปกติ foreach (Character character in characters) { character.workStatus = Character.WorkStatus.Working; } //เอาไว้ไปโชว์หน้า result panel StringBuilder questLog; questLog = new StringBuilder(); //เอาไว้ไปโชว์หน้า result panel StringBuilder detailLog; detailLog = new StringBuilder(); questLog.AppendLine($"\n<color=red> QUEST LOG </color>"); questLog.AppendLine($"\nStarting {questData.questName} . . ."); detailLog.AppendLine($"\n<color=red> FIGHT LOG </color>"); detailLog.AppendLine($"\nStarting {questData.questName} . . ."); //เกี่ยวกับการต่อสู้ DoBattle(characters, questLog, detailLog, questData, quest); //โชว์ ResultPanel ShowResultPanel(GetQuestReward(characters, questLog, questData), questLog, detailLog); //เลิก lock team BuildManager.Instance.AllBuildings.SingleOrDefault(b => b.Type == Building.BuildingType.TownBase).TeamLockState.Remove(quest.teamNumber); NotificationManager.Instance.RemoveActivity(quest); LoadManager.Instance.SavePlayerDataToJson(); return; }
void OnActivityFinished(ActivityInformation activityInformation) { if (activityInformation.activityType == ActivityType.Build) { if (BuildingManager.Instance.AllBuildings.SingleOrDefault(b => b.ID == activityInformation.informationID).Type != Building.BuildingType.Residence) { return; } List <Builder> allResidences = BuildingManager.Instance.AllBuildings.Where(b => b.Type == Building.BuildingType.Residence).ToList(); Building residenceData = LoadManager.Instance.allBuildingData[Building.BuildingType.Residence]; int maxCharacter = 0; foreach (Builder residence in allResidences) { maxCharacter += residenceData.production[residence.Level]["MaxCharacterStored"]; } MaxCharacterInGame = maxCharacter; } }
public void OnActivityFinished(ActivityInformation activityInformation) { RefreshCanvas(); }
public void InitializeData(ActivityInformation information) { this.builder = BuildingManager.Instance.AllBuildings.SingleOrDefault(b => b.ID == information.builderReferenceID); this.activityInformation = information; }
public void OnActivityAssigned(ActivityInformation activityInformation) { RefreshCanvas(); }
public void ActivityAssigned(ActivityInformation activityInformation) { OnActivityAssigned?.Invoke(activityInformation); }
void DoBattle(List <Character> characters, StringBuilder questLog, StringBuilder detailLog, QuestData questData, ActivityInformation quest) { //สร้างลืสมาเก็บศัตรูของเควสนั้นๆ List <Enemy> enemies = new List <Enemy>(); foreach (Enemy enemy in LoadManager.Instance.allEnemyData.Where(e => questData.enemiesIDList.Contains(e.ID))) { //ใช้การโคลน จะทำให้ทุกครั้งที่เข้าด่านเดิม ศัตรูจะเป็นเหมือนตัวใหม่เลือดเต้มตลอด enemies.Add(ObjectCopier.Clone(enemy)); } //เอาลีดเดอร์มาคิดคำนวณอะไรด้านล่าง Character leader = characters[0]; int teamSpeed = characters.Sum(c => c.Stats.speed); int enemiesSpeed = enemies.Sum(e => e.Stats.speed); //ลูปนี้ไว้ใช้กับ questLog foreach (Enemy enemy in enemies) { Debug.Log("enemy CurrentHp" + enemy.CurrentHp.ToString()); questLog.AppendLine($"Wild {enemy.Name} appears !"); } //ถ้าตรงตามเงื่อนไข จะถือว่าจบเควสนั้นเลย ได้ของ บลาๆ เพราะหลบหลีกได้ if ((leader.Stats.intelligence >= enemies[0].Stats.intelligence * 5) && (teamSpeed > enemiesSpeed)) // **************** { foreach (Enemy enemy in enemies) { // Debug.Log($"Thanks to leader({leader.Name}) intelligence({leader.Stats.intelligence}), \nteam successfully avoid encountering {enemy.Name}({enemy.Stats.intelligence})."); questLog.AppendLine($"Thanks to leader({leader.Name}) intelligence({leader.Stats.intelligence}),\n team successfully avoid encountering {enemy.Name}({enemy.Stats.intelligence})."); detailLog.AppendLine($"Thanks to leader({leader.Name}) intelligence({leader.Stats.intelligence}),\n team successfully avoid encountering {enemy.Name}({enemy.Stats.intelligence})."); } } //ถ้าไม่ได้ก็ต้องสู้จ้า else { //สำหรัวหน้า result panel foreach (Enemy enemy in enemies) { questLog.AppendLine($"Start a battle with {enemy.Name} !"); detailLog.AppendLine($"\nStart a battle with {enemy.Name} !"); } //ค่าเริ่มต้นของ ActionPoint InitActionPoint(characters, enemies); //ถ้าเลือกหลีกเลี่ยงการสู้ if (quest.AvoidBattle) { Debug.Log("AvoidBattle"); detailLog.AppendLine($"Try to run away from {(enemies.Count > 1 ? "enemies" : "enemy")} !"); //ถ้าหนีไม่ได้ if (!TryRunForLife()) { Debug.Log("Fail to run away"); detailLog.AppendLine($"Fail to run away from the {(enemies.Count > 1 ? "enemies" : "enemy")}!"); //เริ่มเทิร์น while (!CalculateBattleTurn(characters, enemies, questLog, detailLog, questData)) { ; } //พอเสร็จเซทเทิร์นเป็น 0 ก่อน turn = 0; } else { Debug.Log("Avoid success."); detailLog.AppendLine($"Successfully run away from the {(enemies.Count > 1 ? "enemies" : "enemy")}."); //หนีได้ไปโชว์หน้าสรุปเลย ShowCharactersHP(characters, questData.EXPreceived, questLog, detailLog); } } else //ถ้าไม่เลือกหลีกเลี่ยง มันจะต่อสู้เลย { //เริ่มเทิร์น m Debug.Log("DidntAvoidBattle"); while (!CalculateBattleTurn(characters, enemies, questLog, detailLog, questData)) { ; } turn = 0; } } }
public void ActivityFinished(ActivityInformation activityInformation) { OnActivityFinished?.Invoke(activityInformation); }
public void OnActivityFinished(ActivityInformation activityInformation) { switch (activityInformation.activityType) { case ActivityType.Quest: { /// Update in Notification Panel break; } case ActivityType.Craft: { Resource resource = LoadManager.Instance.allResourceData.SingleOrDefault(r => r.Value.ID == activityInformation.informationID).Value; ItemManager.Instance.AddResource(resource.Name, 1); PointTimer craftTimer = NotificationManager.Instance.gameObject.transform.Find("ActivitiesList/" + activityInformation.activityID).GetComponent <PointTimer>(); Destroy(craftTimer.gameObject); RemoveActivity(activityInformation); break; } case ActivityType.Build: { RemoveActivity(activityInformation); break; } case ActivityType.Pregnancy: { Character femaleCharacter = CharacterManager.Instance.AllCharacters.SingleOrDefault(c => c.ID == activityInformation.informationID); Character maleCharacter = CharacterManager.Instance.AllCharacters.SingleOrDefault(c => c.ID == activityInformation.informationID2); femaleCharacter.workStatus = Character.WorkStatus.Working; CharacterManager.Instance.CreateChildCharacter(maleCharacter, femaleCharacter); ClockTimer timer = NotificationManager.Instance.gameObject.transform.Find("ActivitiesList/" + activityInformation.activityID).GetComponent <ClockTimer>(); Destroy(timer.gameObject); RemoveActivity(activityInformation); break; } case ActivityType.CharacterGrowing: { ClockTimer timer = NotificationManager.Instance.gameObject.transform.Find("ActivitiesList/" + activityInformation.activityID).GetComponent <ClockTimer>(); Destroy(timer.gameObject); RemoveActivity(activityInformation); Character character = CharacterManager.Instance.AllCharacters.SingleOrDefault(c => c.ID == activityInformation.informationID); character.workStatus = Character.WorkStatus.Idle; break; } default: { Debug.LogWarning($"{activityInformation.activityType} is currently unhandled."); break; } } }
protected virtual void OnActivityAssigned(ActivityInformation activityInformation) { }
private void OnActivityAssigned(ActivityInformation activityInformation) { }
private void OnActivityFinished(ActivityInformation activityInformation) { RefreshNotificationAmount(); }
/// <summary> /// Updates an existing activity in the database. Then a new neighborhood action is created to propagate the changes to the neighborhood /// if this is required. If the update is rejected, the action is deleted from the database and this is propagated to the neighborhood. /// <para>Note that the change in activity is not propagated if the client sets no propagation flag in the request, or if only the activity /// expiration date or its location is changed.</para> /// </summary> /// <param name="UpdateRequest">Update request received from the client.</param> /// <param name="Signature">Signature of the updated activity data from the client.</param> /// <param name="OwnerIdentityId">Network ID of the client who requested the update.</param> /// <param name="CloserServerId">If the result is Status.ErrorRejected, this is filled with network identifier of a neighbor server that is closer to the target location.</param> /// <returns>Status.Ok if the function succeeds, /// Status.ErrorNotFound if the activity to update does not exist, /// Status.ErrorRejected if the update was rejected and the client should migrate the activity to closest proximity server, /// Status.ErrorInvalidValue if the update attempted to change activity's type, /// Status.ErrorInternal otherwise.</returns> public async Task <Status> UpdateAndPropagateAsync(UpdateActivityRequest UpdateRequest, byte[] Signature, byte[] OwnerIdentityId, StrongBox <byte[]> CloserServerId) { log.Trace("(UpdateRequest.Activity.Id:{0},OwnerIdentityId:'{1}')", UpdateRequest.Activity.Id, OwnerIdentityId.ToHex()); Status res = Status.ErrorInternal; bool success = false; bool signalNeighborhoodAction = false; bool migrateActivity = false; ActivityInformation activityInformation = UpdateRequest.Activity; DatabaseLock[] lockObjects = new DatabaseLock[] { UnitOfWork.PrimaryActivityLock, UnitOfWork.FollowerLock, UnitOfWork.NeighborhoodActionLock }; using (IDbContextTransaction transaction = await unitOfWork.BeginTransactionWithLockAsync(lockObjects)) { try { PrimaryActivity existingActivity = (await GetAsync(a => (a.ActivityId == activityInformation.Id) && (a.OwnerIdentityId == OwnerIdentityId))).FirstOrDefault(); if (existingActivity != null) { // First, we check whether the activity should be migrated to closer proximity server. GpsLocation oldLocation = existingActivity.GetLocation(); GpsLocation newLocation = new GpsLocation(activityInformation.Latitude, activityInformation.Longitude); bool locationChanged = !oldLocation.Equals(newLocation); bool error = false; if (locationChanged) { List <byte[]> ignoreServerIds = new List <byte[]>(UpdateRequest.IgnoreServerIds.Select(i => i.ToByteArray())); if (!await unitOfWork.NeighborRepository.IsServerNearestToLocationAsync(newLocation, ignoreServerIds, CloserServerId, ProxMessageBuilder.ActivityMigrationDistanceTolerance)) { if (CloserServerId.Value != null) { migrateActivity = true; log.Debug("Activity's new location is outside the reach of this proximity server, the activity will be deleted from the database."); } else { error = true; } } // else No migration needed } if (!error) { // If it should not be migrated, we update the activity in our database. if (!migrateActivity) { SignedActivityInformation signedActivityInformation = new SignedActivityInformation() { Activity = activityInformation, Signature = ProtocolHelper.ByteArrayToByteString(Signature) }; PrimaryActivity updatedActivity = ActivityBase.FromSignedActivityInformation <PrimaryActivity>(signedActivityInformation); ActivityChange changes = existingActivity.CompareChangeTo(updatedActivity); if ((changes & ActivityChange.Type) == 0) { bool propagateChange = false; if (!UpdateRequest.NoPropagation) { // If only changes in the activity are related to location or expiration time, the activity update is not propagated to the neighborhood. propagateChange = (changes & ~(ActivityChange.LocationLatitude | ActivityChange.LocationLongitude | ActivityChange.PrecisionRadius | ActivityChange.ExpirationTime)) != 0; } existingActivity.CopyFromSignedActivityInformation(signedActivityInformation); Update(existingActivity); if (propagateChange) { // The activity has to be propagated to all our followers we create database actions that will be processed by dedicated thread. signalNeighborhoodAction = await unitOfWork.NeighborhoodActionRepository.AddActivityFollowerActionsAsync(NeighborhoodActionType.ChangeActivity, existingActivity.ActivityId, existingActivity.OwnerIdentityId); } else { log.Trace("Change of activity ID {0}, owner identity ID '{1}' won't be propagated to neighborhood.", existingActivity.ActivityId, existingActivity.OwnerIdentityId.ToHex()); } await unitOfWork.SaveThrowAsync(); transaction.Commit(); success = true; } else { log.Debug("Activity ID {0}, owner identity ID '{1}' attempt to change type.", activityInformation.Id, OwnerIdentityId.ToHex()); res = Status.ErrorInvalidValue; } } // else this is handled below separately, out of locked section } // else Internal error } else { log.Debug("Activity ID {0}, owner identity ID '{1}' does not exist.", activityInformation.Id, OwnerIdentityId.ToHex()); res = Status.ErrorNotFound; } } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); } if (!success) { log.Warn("Rolling back transaction."); unitOfWork.SafeTransactionRollback(transaction); } unitOfWork.ReleaseLock(lockObjects); } if (migrateActivity) { // If activity should be migrated, we delete it from our database and inform our neighbors. StrongBox <bool> notFound = new StrongBox <bool>(false); if (await DeleteAndPropagateAsync(activityInformation.Id, OwnerIdentityId, notFound)) { if (!notFound.Value) { // The activity was deleted from the database and this change will be propagated to the neighborhood. log.Debug("Update rejected, activity ID {0}, owner identity ID '{1}' deleted.", activityInformation.Id, OwnerIdentityId.ToHex()); res = Status.ErrorRejected; } else { // Activity of given ID not found among activities created by the client. res = Status.ErrorNotFound; } } } if (success) { // Send signal to neighborhood action processor to process the new series of actions. if (signalNeighborhoodAction) { Network.NeighborhoodActionProcessor neighborhoodActionProcessor = (Network.NeighborhoodActionProcessor)Base.ComponentDictionary[Network.NeighborhoodActionProcessor.ComponentName]; neighborhoodActionProcessor.Signal(); } res = Status.Ok; } log.Trace("(-):{0}", res); return(res); }
/// <summary> /// Validates ActivityInformation structure by itself. This function does not touch database and does not validate /// anything that depends on the context. /// </summary> /// <param name="Activity">Description of the activity to validate.</param> /// <param name="OwnerIdentityPublicKey">Public key of the activity's owner identity.</param> /// <param name="MessageBuilder">Network message builder of the client who sent this activity description.</param> /// <param name="RequestMessage">Full request message from client.</param> /// <param name="ErrorPrefix">Prefix to add to the validation error details.</param> /// <param name="ErrorResponse">If the function fails, this is filled with error response message that is ready to be sent to the client.</param> /// <returns>true if the activity information is valid, false otherwise.</returns> public static bool ValidateActivityInformation(ActivityInformation Activity, byte[] OwnerIdentityPublicKey, ProxMessageBuilder MessageBuilder, ProxProtocolMessage RequestMessage, string ErrorPrefix, out ProxProtocolMessage ErrorResponse) { log.Trace("()"); bool res = false; ErrorResponse = null; string details = null; if (Activity == null) { Activity = new ActivityInformation(); } if (Activity.ProfileServerContact == null) { Activity.ProfileServerContact = new ServerContactInfo(); } SemVer version = new SemVer(Activity.Version); // Currently only supported version is 1.0.0. if (!version.Equals(SemVer.V100)) { log.Debug("Unsupported version '{0}'.", version); details = "version"; } if (details == null) { uint activityId = Activity.Id; // 0 is not a valid activity identifier. if (activityId == 0) { log.Debug("Invalid activity ID '{0}'.", activityId); details = "id"; } } if (details == null) { byte[] pubKey = Activity.OwnerPublicKey.ToByteArray(); bool pubKeyValid = (0 < pubKey.Length) && (pubKey.Length <= ProtocolHelper.MaxPublicKeyLengthBytes) && ByteArrayComparer.Equals(OwnerIdentityPublicKey, pubKey); if (!pubKeyValid) { log.Debug("Invalid public key '{0}' does not match identity public key '{1}'.", pubKey.ToHex(), OwnerIdentityPublicKey.ToHex()); details = "ownerPublicKey"; } } if (details == null) { ServerContactInfo sci = Activity.ProfileServerContact; bool networkIdValid = sci.NetworkId.Length == ProtocolHelper.NetworkIdentifierLength; IPAddress ipAddress = IPAddressExtensions.IpFromBytes(sci.IpAddress.ToByteArray()); bool ipAddressValid = (ipAddress != null) && (Config.Configuration.TestModeEnabled || !ipAddress.IsReservedOrLocal()); bool portValid = (1 <= sci.PrimaryPort) && (sci.PrimaryPort <= 65535); if (!networkIdValid || !ipAddressValid || !portValid) { log.Debug("Profile server contact's network ID is {0}, IP address is {1}, port is {2}.", networkIdValid ? "valid" : "invalid", ipAddressValid ? "valid" : "invalid", portValid ? "valid" : "invalid"); if (!networkIdValid) { details = "profileServerContact.networkId"; } else if (!ipAddressValid) { details = "profileServerContact.ipAddress"; } else if (!portValid) { details = "profileServerContact.primaryPort"; } } } if (details == null) { string activityType = Activity.Type; if (activityType == null) { activityType = ""; } int byteLen = Encoding.UTF8.GetByteCount(activityType); bool activityTypeValid = (0 < byteLen) && (byteLen <= ProxMessageBuilder.MaxActivityTypeLengthBytes); if (!activityTypeValid) { log.Debug("Activity type too long or zero length ({0} bytes, limit is {1}).", byteLen, ProxMessageBuilder.MaxActivityTypeLengthBytes); details = "type"; } } if (details == null) { GpsLocation locLat = new GpsLocation(Activity.Latitude, 0); GpsLocation locLong = new GpsLocation(0, Activity.Longitude); if (!locLat.IsValid()) { log.Debug("Latitude '{0}' is not a valid GPS latitude value.", Activity.Latitude); details = "latitude"; } else if (!locLong.IsValid()) { log.Debug("Longitude '{0}' is not a valid GPS longitude value.", Activity.Longitude); details = "longitude"; } } if (details == null) { uint precision = Activity.Precision; bool precisionValid = (0 <= precision) && (precision <= ProxMessageBuilder.MaxLocationPrecision); if (!precisionValid) { log.Debug("Precision '{0}' is not an integer between 0 and {1}.", precision, ProxMessageBuilder.MaxLocationPrecision); details = "precision"; } } if (details == null) { DateTime?startTime = ProtocolHelper.UnixTimestampMsToDateTime(Activity.StartTime); DateTime?expirationTime = ProtocolHelper.UnixTimestampMsToDateTime(Activity.ExpirationTime); if (startTime == null) { log.Debug("Invalid activity start time timestamp '{0}'.", Activity.StartTime); details = "startTime"; } else if (expirationTime == null) { log.Debug("Invalid activity expiration time timestamp '{0}'.", Activity.ExpirationTime); details = "expirationTime"; } else { if (startTime > expirationTime) { log.Debug("Activity expiration time has to be greater than or equal to its start time."); details = "expirationTime"; } else if (expirationTime.Value > DateTime.UtcNow.AddHours(ActivityBase.MaxActivityLifeTimeHours)) { log.Debug("Activity expiration time {0} is more than {1} hours in the future.", expirationTime.Value.ToString("yyyy-MM-dd HH:mm:ss"), ActivityBase.MaxActivityLifeTimeHours); details = "expirationTime"; } } } if (details == null) { string extraData = Activity.ExtraData; if (extraData == null) { extraData = ""; } // Extra data is semicolon separated 'key=value' list, max ActivityBase.MaxActivityExtraDataLengthBytes bytes long. int byteLen = Encoding.UTF8.GetByteCount(extraData); if (byteLen > ProxMessageBuilder.MaxActivityExtraDataLengthBytes) { log.Debug("Extra data too large ({0} bytes, limit is {1}).", byteLen, ProxMessageBuilder.MaxActivityExtraDataLengthBytes); details = "extraData"; } } if (details == null) { res = true; } else { ErrorResponse = MessageBuilder.CreateErrorInvalidValueResponse(RequestMessage, ErrorPrefix + details); } log.Trace("(-):{0}", res); return(res); }