Exemple #1
0
        public void Update(Action <IDocumentMetadataBuilder> update)
        {
            var settings = MetadataProvider.CreateEmpty();

            update(settings);
            settings.Apply(Metadata);
            OnMetadataUpdated?.Invoke(this, EventArgs.Empty);
        }
Exemple #2
0
        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);
                }
            }
        }
Exemple #3
0
        /// <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);
        }
Exemple #4
0
        /// <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 });
                    }
                }
            }
        }