public void Update(Action <IDocumentMetadataBuilder> update) { var settings = MetadataProvider.CreateEmpty(); update(settings); settings.Apply(Metadata); OnMetadataUpdated?.Invoke(this, EventArgs.Empty); }
void LoadMetadataForPage(string pageName) { if (PageName != pageName) { PageName = pageName; bool hasChanges = RevertPageSpecificMetaData != null; if (hasChanges) { RevertPageSpecificMetaData(); } var builder = MetadataProvider.GetByPageName(PageName); if (hasChanges = (hasChanges || builder != null)) { RevertPageSpecificMetaData = builder?.Apply(Metadata); } if (hasChanges) { OnMetadataUpdated?.Invoke(this, EventArgs.Empty); } } }
/// <summary> /// Listen for packets coming in from the server and handle them accordingly. /// </summary> /// <param name="stream">PacketStream in use by the Control thread.</param> /// <returns>True if the server has asked us to disconnect.</returns> private bool Listen(PacketStream stream) { while (stream.Connected && stream.DataAvailable) { //read incoming packet Packet packet = null; if (CaptureException(() => { packet = stream.Read(); })) { break; } //check if guid of sender matches server if (!packet.SenderID.Equals(serverID)) { continue; //ignore } switch (packet.PayloadType) { case DisconnectionRequest.PayloadType: //disconnection request from server return(true); case OperationList.PayloadType: //operation list (4) /* * COMP7722: step 4 of HOB: incoming operations are appended to the local * incoming operation buffer. */ if (awaitingOperationList) { OperationList operationList = null; if (CaptureException(() => { operationList = packet.Payload.Deserialize <OperationList>(); })) { break; } if (operationList.Operations != null && operationList.Operations.Count > 0) { incomingOperations.AddRange(operationList.Operations); } awaitingOperationList = false; } break; case ClientMetadata.PayloadType: { //deserialize metadata packet ClientMetadata metadataPacket = null; if (CaptureException(() => { metadataPacket = packet.Payload.Deserialize <ClientMetadata>(); }) || metadataPacket.Metadata == null || metadataPacket.Metadata.Count == 0) { break; } if (metadataPacket.Metadata != null && OnMetadataUpdated != null) { foreach (var md in metadataPacket.Metadata) { OnMetadataUpdated?.Invoke(this, md.Key, md.Value); } } } break; } } return(false); }
/// <summary> /// Connect to an OTEX server. /// </summary> /// <param name="endpoint">IP Endpoint (address and port) of the OTEX server.</param> /// <param name="password">Password required to connect to the server, if any. Leave as null for none.</param> /// <param name="metadata">Client-specific application data to send to the server.</param> /// <exception cref="ArgumentException" /> /// <exception cref="ArgumentNullException" /> /// <exception cref="ArgumentOutOfRangeException" /> /// <exception cref="ObjectDisposedException" /> /// <exception cref="SocketException" /> /// <exception cref="InvalidDataException" /> /// <exception cref="System.Runtime.Serialization.SerializationException" /> /// <exception cref="System.Security.SecurityException" /> /// <exception cref="IOException" /> /// <exception cref="InvalidOperationException" /> public void Connect(IPEndPoint endpoint, Password password = null, byte[] metadata = null) { if (isDisposed) { throw new ObjectDisposedException("OTEX.Client"); } if (!connected) { lock (connectedLock) { if (isDisposed) { throw new ObjectDisposedException("OTEX.Client"); } if (connected) { throw new InvalidOperationException("Client is already connected to a server. Call Disconnect() first."); } if (!connected) { //check endpoint if (endpoint == null) { throw new ArgumentNullException("endpoint"); } if (endpoint.Port < 1024 || Server.AnnouncePorts.Contains(endpoint.Port)) { throw new ArgumentOutOfRangeException("endpoint.Port", string.Format("Port must be between 1024-{0} or {1}-65535.", Server.AnnouncePorts.First - 1, Server.AnnouncePorts.Last + 1)); } if (endpoint.Address.Equals(IPAddress.Any) || endpoint.Address.Equals(IPAddress.Broadcast) || endpoint.Address.Equals(IPAddress.None) || endpoint.Address.Equals(IPAddress.IPv6Any) || endpoint.Address.Equals(IPAddress.IPv6None)) { throw new ArgumentOutOfRangeException("endpoint.Address", "Address cannot be Any, None or Broadcast."); } //check metadata if (metadata != null && metadata.Length > ClientMetadata.MaxSize) { throw new ArgumentOutOfRangeException("metadata", string.Format("metadata.Length may not be greater than {0}.", ClientMetadata.MaxSize)); } //session connection TcpClient tcpClient = null; PacketStream packetStream = null; Packet responsePacket = null; ConnectionResponse response = null; try { //establish tcp connection tcpClient = new TcpClient(AddressFamily.InterNetworkV6); tcpClient.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false); tcpClient.Connect(endpoint); packetStream = new PacketStream(tcpClient); //send connection request packet packetStream.Write(ID, new ConnectionRequest(password, metadata)); //get response responsePacket = packetStream.Read(); if (responsePacket.SenderID.Equals(Guid.Empty)) { throw new InvalidDataException("responsePacket.SenderID was Guid.Empty"); } if (responsePacket.PayloadType != ConnectionResponse.PayloadType) { throw new InvalidDataException("unexpected response packet type"); } response = responsePacket.Payload.Deserialize <ConnectionResponse>(); if (response.Result != ConnectionResponse.ResponseCode.Approved) { throw new Exception(string.Format("connection rejected by server: {0}", response.Result)); } } catch (Exception) { if (packetStream != null) { packetStream.Dispose(); } if (tcpClient != null) { tcpClient.Close(); } throw; } //set connected state connected = true; clientSideDisconnection = false; serverPort = (ushort)endpoint.Port; serverAddress = endpoint.Address; serverFilePath = response.FilePath ?? ""; serverName = response.Name ?? ""; serverID = responsePacket.SenderID; awaitingOperationList = false; //fire events OnConnected?.Invoke(this); InvokeRemoteOperations(response.Operations); if (response.Metadata != null && OnMetadataUpdated != null) { foreach (var md in response.Metadata) { OnMetadataUpdated?.Invoke(this, md.Key, md.Value); } } //create management thread thread = new Thread(ControlThread); thread.Name = "OTEX Client ControlThread"; thread.IsBackground = false; thread.Start(new object[] { tcpClient, packetStream }); } } } }