コード例 #1
0
    public void receiveUpdate(DatagramIn dg, IDistributedObject distObj, UInt16 field_id)
    {
        Debug.Log("Receive update for class " + distObj.getClass() + " field ID" + field_id);

        // first get the array of fields we'll need to unpack

        string[] t_fields = DCFile.fieldLookup[field_id];

        // next, define an empty array of params the size of the number of fields
        object[] t_params = new object[t_fields.Length];

        // unpack the parameters

        for (int i = 0; i < t_fields.Length; ++i)
        {
            t_params[i] = unserializeType(dg, t_fields[i]);
        }

        // finally, use reflection to call the function
        Type t_type = distObj.GetType();

        MethodInfo t_method = t_type.GetMethod(DCFile.fieldNameLookup[field_id]);

        t_method.Invoke(distObj, t_params);
    }
コード例 #2
0
        // Add this DistributedObject to the repository.
        public void AddObject(IDistributedObject obj)
        {
            DistributedObjectId doId = obj.DistributedObjectId;

            // Store in the dictionary of objects
            mObjectIds[doId] = obj;
        }
コード例 #3
0
        /// <summary>
        ///  Returns the object referenced by the doId or null if not found on this state server.
        /// </summary>
        /// <param name="doId"></param>
        /// <returns></returns>
        public IDistributedObject GetObject(DistributedObjectId doId)
        {
            IDistributedObject obj = null;

            mObjectIds.TryGetValue(doId, out obj);
            return(obj);
        }
 /// <summary>
 /// Gets a disposable object that will destroy and dispose a distributed
 /// object when disposed.
 /// </summary>
 /// <param name="o">The object.</param>
 /// <returns>A disposable object.</returns>
 protected IAsyncDisposable DestroyAndDispose(IDistributedObject o)
 {
     return(new AsyncDisposable(async() =>
     {
         await Client.DestroyAsync(o);
         await o.DisposeAsync();
     }));
 }
コード例 #5
0
        /*******************************/
        // IMessageRouter Functions
        /*******************************/
        public void ReceiveMessage(Message message)
        {
            switch (message.MessageType)
            {
            case MessageType.Create:
                IClientDistributedObject distributedObject = mDistributedObjectFactory.CreateDistributedObject(message.DistributedObjectId, message.Data);
                if (distributedObject != null)
                {
                    this.AddObject(distributedObject);
                    List <System.Action <IClientDistributedObject> > requestedObjectCallbacks = null;
                    if (mAnticipatedDistributedObjectIdsToCallbacks.TryGetValue(distributedObject.DistributedObjectId, out requestedObjectCallbacks))
                    {
                        foreach (System.Action <IClientDistributedObject> requestedObjectCallback in requestedObjectCallbacks)
                        {
                            requestedObjectCallback(distributedObject);
                        }
                        mAnticipatedDistributedObjectIdsToCallbacks.Remove(distributedObject.DistributedObjectId);
                    }
                }
                break;

            case MessageType.Update:
                DistributedObjectId doId         = message.DistributedObjectId;
                IDistributedObject  updateObject = null;
                if (mObjectIds.TryGetValue(doId, out updateObject))
                {
                    updateObject.ProcessMessage(message);
                }
                else
                {
                    Console.LogError("Message update but objectId " + doId + " not found in repository");
                }
                break;

            case MessageType.Delete:
                DistributedObjectId deletedoId = message.DistributedObjectId;
                IDistributedObject  deleteObject;

                if (mObjectIds.TryGetValue(deletedoId, out deleteObject))
                {
                    if (deleteObject is ClientDistributedObject)
                    {
                        ClientDistributedObject deleteClientObject = deleteObject as ClientDistributedObject;
                        if (deleteClientObject != null)
                        {
                            deleteClientObject.Dispose();
                        }
                    }
                    this.RemoveObject(deleteObject);
                }
                else
                {
                    Console.LogError("Message delete but objectId " + deletedoId.ToString() + " not found in repository");
                }
                break;
            }
        }
コード例 #6
0
 internal DistributedObjectEvent(DistributedEventType eventType, string serviceName, string objectName,
                                 IDistributedObject distributedObject, Guid source, ProxyManager proxyManager)
 {
     EventType          = eventType;
     ServiceName        = serviceName;
     ObjectName         = objectName;
     _distributedObject = distributedObject;
     Source             = source;
     _proxyManager      = proxyManager;
 }
コード例 #7
0
        /// <summary>
        /// This is a new owner DistributedObject entering the system on this peer.
        /// </summary>
        internal void AddOwner(IDistributedObject distributedObject)
        {
            owners.Add(distributedObject.Id, distributedObject);

            // and tell all the peers
            // TODO: invert this so we create the message, write it to NetDataWriter, and then just blast it to all peers
            foreach (NetPeer netPeer in netManager.ConnectedPeerList)
            {
                distributedObject.DistributedType.SendCreateMessageInternal(netPeer);
            }
        }
コード例 #8
0
        // Remove this DistributedObject from the repository.
        public virtual void RemoveObject(IDistributedObject obj)
        {
            // Remove from object id dict
            DistributedObjectId doId = obj.DistributedObjectId;

            if (!mObjectIds.Remove(doId))
            {
                Console.WriteLine("Warning!!! We don't have this object!");
                return;
            }
        }
コード例 #9
0
 // Remove this DistributedObject from the repository.
 public override void RemoveObject(IDistributedObject obj)
 {
     if (obj.GetType().IsAssignableFrom(typeof(IServerDistributedObject)))
     {
         // Upcast to server version so we get the extra cleanup
         this.RemoveObject((IServerDistributedObject)obj);
     }
     else
     {
         // Just call the base class version
         base.RemoveObject(obj);
     }
 }
コード例 #10
0
        public T GetDistributedObject <T>() where T : IDistributedObject
        {
            if (DistributedEventType.DESTROYED == EventType)
            {
                throw new DistributedObjectDestroyedException();
            }

            if (!(_distributedObject is T))
            {
                _distributedObject = _proxyManager.GetOrCreateProxy <T>(ServiceName, ObjectName);
            }

            return((T)_distributedObject);
        }
コード例 #11
0
        /// <summary>
        /// Destroys a distributed object.
        /// </summary>
        /// <param name="o">The distributed object.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        public async ValueTask DestroyAsync(IDistributedObject o, CancellationToken cancellationToken = default)
        {
            // try to get the object - and then, dispose it

            var info    = new DistributedObjectInfo(o.ServiceName, o.Name);
            var attempt = await _objects.TryGetAndRemoveAsync(info).CfAwait();

            if (attempt)
            {
                await TryDispose(attempt.Value).CfAwait();
            }

            var ob = (DistributedObjectBase)o;  // we *know* all our objects inherit from the base object
            await ob.DestroyingAsync().CfAwait();

            await DestroyAsync(o.ServiceName, o.Name, cancellationToken).CfAwait();
        }
コード例 #12
0
        /// <summary>
        /// Delete this owner object from this Peer's tables.
        /// </summary>
        internal void Delete(IDistributedObject distributedObject, Action <NetPeer, bool> sendDeleteMessage)
        {
            Contract.Requires(distributedObject != null);
            Contract.Requires(sendDeleteMessage != null);
            Contract.Requires(distributedObject.Host == this);

            if (distributedObject.IsOwner)
            {
                owners.Remove(distributedObject.Id);
                // TODO: invert this so we create the message once and blast it to all peers
                foreach (NetPeer netPeer in NetPeers)
                {
                    sendDeleteMessage(netPeer, false);
                }
            }
            else
            {
                sendDeleteMessage(distributedObject.OwningPeer, true);
            }
        }
コード例 #13
0
        public void HostCreateThenDisconnect()
        {
            var testWorkQueue = new WorkQueue();

            // the first host under test
            using DistributedHost host = CreateHost(testWorkQueue, true);

            // create object
            var distributedThing = new DistributedThing(host, new LocalThing());

            // construct second host
            using (DistributedHost host2 = CreateHost(testWorkQueue, false))
            {
                // consume one owner ID so second object has ID 2 instead of (matching first object) ID 1
                host2.NextOwnerId();

                // now create an owner object on the other host
                var distributedThing2 = new DistributedThing(host2, new LocalThing());

                // host could start announcing also, but host2 isn't listening so it wouldn't be detectable
                host2.Announce();

                // wait until the proxy for the new object makes it to the other host
                WaitUtils.WaitUntil(new[] { host, host2 }, () =>
                                    host2.NetPeers.Count() == 1 &&
                                    ProxiesForFirstPeer(host2).Count == 1 &&
                                    host.NetPeers.Count() == 1 &&
                                    ProxiesForFirstPeer(host).Count == 1);

                IDistributedObject host2Proxy = ProxiesForFirstPeer(host2).Values.First();
                Assert.AreEqual(new DistributedId(1), host2Proxy.Id);
                Assert.False(host2Proxy.IsOwner);

                IDistributedObject hostProxy = ProxiesForFirstPeer(host).Values.First();
                Assert.AreEqual(new DistributedId(2), hostProxy.Id);
                Assert.False(hostProxy.IsOwner);
            }

            // now after things settle down there should be no proxy
            WaitUtils.WaitUntil(new[] { host }, () => host.PeerCount == 0 && host.ProxyPeerCount == 0);
        }
コード例 #14
0
        /// <summary>
        /// Destroys a distributed object.
        /// </summary>
        /// <param name="o">The distributed object.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        public async ValueTask DestroyAsync(IDistributedObject o, CancellationToken cancellationToken = default)
        {
            // try to get the object - and then, dispose it

            var info    = new DistributedObjectInfo(o.ServiceName, o.Name);
            var attempt = await _objects.TryGetAndRemoveAsync(info).CfAwait();

            if (attempt)
            {
                await TryDispose(attempt.Value).CfAwait();
            }

            var ob = (DistributedObjectBase)o;  // we *know* all our objects inherit from the base object
            await ob.DestroyingAsync().CfAwait();

            // regardless of whether the object was known locally, destroy on server
            var clientMessage   = ClientDestroyProxyCodec.EncodeRequest(o.Name, o.ServiceName);
            var responseMessage = await _cluster.Messaging.SendAsync(clientMessage, cancellationToken).CfAwait();

            _ = ClientDestroyProxyCodec.DecodeResponse(responseMessage);
        }
コード例 #15
0
        private void OnDelete(NetPeer netPeer, DistributedId id, bool isRequest)
        {
            SerializedSocketAddress peerAddress = new SerializedSocketAddress(netPeer);

            if (isRequest)
            {
                // owner id may or may not still exist; it's OK if it doesn't.
                if (!owners.ContainsKey(id))
                {
                    // do nothing; ignore the delete request altogether
                }
                else
                {
                    // we will accept this request... for testing purposes.
                    // TBD if this is the right thing in general!
                    IDistributedObject distributedObject = owners[id];

                    // and tell all proxies
                    foreach (NetPeer proxyPeer in NetPeers)
                    {
                        distributedObject.DistributedType.SendDeleteMessageInternal(proxyPeer, false);
                    }

                    owners.Remove(id);
                    distributedObject.OnDelete();
                }
            }
            else
            {
                // this is an authoritative delete message from the owner.
                // we expect strong consistency here so the id should still exist.
                Contract.Requires(proxies[peerAddress].ContainsKey(id));

                IDistributedObject proxy = proxies[peerAddress][id];
                proxies[peerAddress].Remove(id);
                proxy.Delete();
            }
        }
コード例 #16
0
        public void HostCreateAfterConnection()
        {
            var testWorkQueue = new WorkQueue();

            // the first host under test
            using DistributedHost host = CreateHost(testWorkQueue, true);

            // construct second host
            using DistributedHost host2 = CreateHost(testWorkQueue, false);

            // host could start announcing also, but host2 isn't listening so it wouldn't be detectable
            host2.Announce();

            // should generate announce response and then connection
            WaitUtils.WaitUntil(new[] { host, host2 }, () => host.PeerCount == 1 && host2.PeerCount == 1);

            // create object
            var distributedThing = new DistributedThing(host, new LocalThing());

            // wait until the proxy for the new object makes it to the other host
            WaitUtils.WaitUntil(new[] { host, host2 }, () => ProxiesForFirstPeer(host2).Count == 1);

            IDistributedObject host2Proxy = ProxiesForFirstPeer(host2).Values.First();

            Assert.AreEqual(new DistributedId(1), host2Proxy.Id);
            Assert.False(host2Proxy.IsOwner);

            // now create an owner object on the other host
            var distributedThing2 = new DistributedThing(host2, new LocalThing());

            // wait until the proxy for the new object makes it to the first host
            WaitUtils.WaitUntil(new[] { host, host2 }, () => ProxiesForFirstPeer(host).Count == 1);

            IDistributedObject hostProxy = ProxiesForFirstPeer(host).Values.First();

            Assert.AreEqual(new DistributedId(1), hostProxy.Id);
            Assert.False(hostProxy.IsOwner);
        }
コード例 #17
0
        public void HostCreateWithState()
        {
            var testWorkQueue = new WorkQueue();

            // the first host under test
            using DistributedHost host = CreateHost(testWorkQueue, true);

            // construct second host
            using DistributedHost host2 = CreateHost(testWorkQueue, false);

            // host could start announcing also, but host2 isn't listening so it wouldn't be detectable
            host2.Announce();

            // should generate announce response and then connection
            WaitUtils.WaitUntil(new[] { host, host2 }, () => host.PeerCount == 1 && host2.PeerCount == 1);

            // create object
            var distributedThing = new DistributedThing(host, new LocalThing(new[] { 1, 2 }));

            // wait until the proxy for the new object makes it to the other host
            WaitUtils.WaitUntil(new[] { host, host2 }, () => ProxiesForFirstPeer(host2).Count == 1);

            LocalThing host2LocalThing = FirstProxyLocalThing(host2);

            Assert.IsTrue(Enumerable.SequenceEqual(new[] { 1, 2 }, host2LocalThing.LocalValues.ToList()));

            // now create an owner object on the other host
            var distributedThing2 = new DistributedThing(host2, new LocalThing(new[] { 3, 4 }));

            // wait until the proxy for the new object makes it to the first host
            WaitUtils.WaitUntil(new[] { host, host2 }, () => ProxiesForFirstPeer(host).Count == 1);

            IDistributedObject hostProxy      = ProxiesForFirstPeer(host).Values.First();
            LocalThing         hostLocalThing = (LocalThing)hostProxy.LocalObject;

            Assert.IsTrue(Enumerable.SequenceEqual(new[] { 3, 4 }, hostLocalThing.LocalValues.ToList()));
        }
コード例 #18
0
    private void onData(MemoryStream data)
    {
        DatagramIn reader = new DatagramIn(data);

        UInt16 type = reader.ReadUInt16();

        switch ((MessageTypes)type)
        {
        case MessageTypes.CLIENT_HELLO_RESP:
        {
            Debug.Log("Response to client_hello");

            if (onHello != null)
            {
                onHello();
            }
            break;
        }

        case MessageTypes.CLIENT_EJECT:
        {
            UInt16 error_code = reader.ReadUInt16();
            string reason     = reader.ReadString();

            Debug.Log("Ejected Code " + error_code + ": " + reason);

            if (onEject != null)
            {
                onEject(error_code, reason);
            }
            break;
        }

        case MessageTypes.CLIENT_ADD_INTEREST:
        {
            UInt32 context     = reader.ReadUInt32();
            UInt16 interest_id = reader.ReadUInt16();
            UInt32 parent_id   = reader.ReadUInt32();
            UInt32 zone_id     = reader.ReadUInt32();

            Interest newInterest = new Interest(context, interest_id, zone_id, parent_id);
            context2interest.Add(context, newInterest);

            if (onAddInterest != null)
            {
                onAddInterest(newInterest);
            }

            break;
        }

        case MessageTypes.CLIENT_DONE_INTEREST_RESP:
        {
            UInt32 context     = reader.ReadUInt32();
            UInt16 interest_id = reader.ReadUInt16();

            if (onDoneInterest != null)
            {
                onDoneInterest(context2interest[context]);
            }

            break;
        }

        case MessageTypes.CLIENT_ENTER_OBJECT_REQUIRED:
        {
            unserializeClass(reader, SerializationLevel.REQUIRED_BCAST, false, false);
            break;
        }

        case MessageTypes.CLIENT_ENTER_OBJECT_REQUIRED_OTHER:
        {
            unserializeClass(reader, SerializationLevel.REQUIRED_BCAST, false, true);
            break;
        }

        case MessageTypes.CLIENT_ENTER_OBJECT_REQUIRED_OWNER:
        {
            unserializeClass(reader, SerializationLevel.REQUIRED_BCAST_OR_OWNRECV, true, false);
            break;
        }

        case MessageTypes.CLIENT_ENTER_OBJECT_REQUIRED_OTHER_OWNER:
        {
            unserializeClass(reader, SerializationLevel.REQUIRED_BCAST_OR_OWNRECV, true, true);
            break;
        }

        case MessageTypes.CLIENT_OBJECT_LOCATION:
        {
            UInt32 do_id     = reader.ReadUInt32();
            UInt32 parent_id = reader.ReadUInt32();
            UInt32 zone_id   = reader.ReadUInt32();

            doId2do[do_id].getLocation().changeLocation(zone_id, parent_id);
            doId2do[do_id].locationChanged();
            break;
        }

        case MessageTypes.CLIENT_OBJECT_LEAVING:
        {
            UInt32 doId = reader.ReadUInt32();
            doId2do[doId].leaving();

            // freeing the DO from the doId2do map is done by the leaving method
            // via the removeDOfromMap function

            // if the leaving method is overriden,
            // removeDOfromMap should still be called to prevent memory leaks
            break;
        }

        case MessageTypes.CLIENT_OBJECT_SET_FIELD:
        {
            UInt32 doId     = reader.ReadUInt32();
            UInt16 field_id = reader.ReadUInt16();

            receiveUpdate(reader, doId2do[doId], field_id);
            break;
        }

        case MessageTypes.CLIENT_OBJECT_SET_FIELDS:
        {
            UInt32 doId = reader.ReadUInt32();

            IDistributedObject distObj = doId2do[doId];

            UInt16 num_fields = reader.ReadUInt16();
            for (int i = 0; i < num_fields; ++i)
            {
                UInt16 field_id = reader.ReadUInt16();
                receiveUpdate(reader, distObj, field_id);
            }
            break;
        }

        default:
        {
            Debug.Log("Unknown message type: " + type);
            break;
        }
        }
    }
コード例 #19
0
 public void AddProxy(NetPeer netPeer, IDistributedObject newProxy)
 {
     Host.AddProxy(new SerializedSocketAddress(netPeer), newProxy);
 }
コード例 #20
0
 /// <inheritdoc />
 public async ValueTask DestroyAsync(IDistributedObject o)
 {
     await _distributedOjects.DestroyAsync(o).CfAwait();
 }
コード例 #21
0
        /// <summary>
        /// This is a new proxy being created on this peer, owned by netPeer.
        /// </summary>
        private void AddProxy(SerializedSocketAddress peerAddress, IDistributedObject proxy)
        {
            Contract.Requires(!proxy.IsOwner);

            proxies[peerAddress].Add(proxy.Id, proxy);
        }
コード例 #22
0
 public DistributedObjectEvent(string eventType, string serviceName, IDistributedObject distributedObject)
 {
     _eventType         = eventType;
     _serviceName       = serviceName;
     _distributedObject = distributedObject;
 }
コード例 #23
0
 /// <inheritdoc />
 public async ValueTask DestroyAsync(IDistributedObject o)
 {
     await _distributedObjectFactory.DestroyAsync(o.ServiceName, o.Name).CAF();
 }
コード例 #24
0
 public DistributedObjectEvent(String eventType, string serviceName, IDistributedObject distributedObject)
 {
     this.eventType         = eventType;
     this.serviceName       = serviceName;
     this.distributedObject = distributedObject;
 }
コード例 #25
0
 public DistributedObjectEvent(string eventType, string serviceName, IDistributedObject distributedObject)
 {
     _eventType = eventType;
     _serviceName = serviceName;
     _distributedObject = distributedObject;
 }
コード例 #26
0
 public DistributedObjectEvent(String eventType, string serviceName, IDistributedObject distributedObject)
 {
     this.eventType = eventType;
     this.serviceName = serviceName;
     this.distributedObject = distributedObject;
 }