public Property(object value, PropertyConflictResolution conflictRes = PropertyConflictResolution.NO_SYNC_ON_CONFLICT) { Value = value; OnConflict = conflictRes; }
/// <summary> /// A synchronization has been requested /// </summary> protected virtual void _SyncRequest(Client client, Packet packet) { if (packet.Id != Packet.SYNC_ID || packet.Specifier != PROP_SYNC_SPEC) { return; } if (packet.ContentLength % 2 != 0) { client.LogNotNull(Logging.LogLevel.ERROR, "PRPSYNC packet received with odd length"); client.Send(new Packet(Packet.PACKET_MALFORMED_HEADER, packet.Id, packet.Specifier) { Designation = "PRPSYNC packet malformed (odd property length)" }); return; } if (packet.Header == Packet.OK_HEADER) { var response = new List <object>(); var toSet = new Dictionary <string, Property>(); var exclude = new List <string>(); for (int i = 0; i < packet.ContentLength; i += 2) { string temp = packet.Get(i) as string; Property prop = packet.Get(i + 1) as Property; if (String.IsNullOrEmpty(temp) || prop == null) { client.LogNotNull(Logging.LogLevel.ERROR, "Malformed PRPSYNC packet received"); client.Send(new Packet(Packet.PACKET_MALFORMED_HEADER, packet.Id, packet.Specifier) { Designation = "PRPSYNC packet malformed. Key null or not a string, or property null or of wrong type" }); return; } if (Has(temp)) { PropertyConflictResolution pcr = Get(temp).OnConflict; if ((pcr == PropertyConflictResolution.CLIENT_OVERWRITE && client.ServerSide) || (pcr == PropertyConflictResolution.SERVER_OVERWRITE && !client.ServerSide)) { toSet.Add(temp, prop); } else if (pcr != PropertyConflictResolution.NO_SYNC && pcr != PropertyConflictResolution.NO_SYNC_ON_CONFLICT) { response.Add(temp); response.Add(Get(temp)); } else { exclude.Add(temp); } } else if (prop.OnConflict != PropertyConflictResolution.NO_SYNC) { toSet.Add(temp, prop); } } foreach (var ts in toSet) { Set(ts.Key, ts.Value, true); } foreach (var entry in Handle) { if (response.Contains(entry.Key) || toSet.ContainsKey(entry.Key) || exclude.Contains(entry.Key)) { continue; } response.Add(entry.Key); response.Add(entry.Value); } client.Send(new Packet(Packet.CONFIRMATION_AWAIT_HEADER, packet.Id, packet.Specifier, response.ToArray()) { Designation = "PRPSYNC conflict resolution" }); } else if (packet.Header == Packet.CONFIRMATION_AWAIT_HEADER) { var toSet = new Dictionary <string, Property>(); for (int i = 0; i < packet.ContentLength; i += 2) { string temp = packet.Get(i) as string; Property prop = packet.Get(i + 1) as Property; if (String.IsNullOrEmpty(temp) || prop == null) { client.LogNotNull(Logging.LogLevel.ERROR, "Malformed PRPSYNC packet received"); client.Send(new Packet(Packet.PACKET_MALFORMED_HEADER, packet.Id, packet.Specifier) { Designation = "PRPSYNC packet malformed. Key null or not a string, or property null or not of type" }); return; } //in case it happens... if (!Has(temp) && prop.OnConflict != PropertyConflictResolution.NO_SYNC) { toSet.Add(temp, prop); continue; } PropertyConflictResolution pcr = prop.OnConflict; if ((pcr == PropertyConflictResolution.CLIENT_OVERWRITE && client.ServerSide) || (pcr == PropertyConflictResolution.SERVER_OVERWRITE && !client.ServerSide)) { toSet.Add(temp, prop); } else { client.LogNotNull(Logging.LogLevel.WARNING, "PRPSYNC conflict couldn't be resolved, inconsistent behaviour. Aborting"); client.Send(new Packet(Packet.AMBIGUITY_HEADER, packet.Id, packet.Specifier) { Designation = "Ambiguous and suspicious conflict resolution packet received" }); return; } } foreach (var ts in toSet) { Set(ts.Key, ts.Value, true); } client.Send(new Packet(Packet.ACK_HEADER, packet.Id, packet.Specifier) { Designation = "ACK ; Synchronization done" }); OnSynchronization(this); } else if (packet.Header == Packet.ACK_HEADER) { OnSynchronization(this); } }