Пример #1
0
        /// <summary>
        /// Serializes a NetMessage to the reliable stream.
        /// If there is no current stream, one is prepared.
        /// If the current stream cannot fit the message, it is sent and a new stream is prepared.
        /// </summary>
        internal void SerializeReliableMessage(NetMessage message)
        {
            if (sendWindow.Count >= 512)
            {
                return;
            }

            if (sendStream == null)
            {
                InitializeStream();
            }

            if (!NetSerializer.TryWriteMessage(sendStream, message))
            {
                if (retryingSerialization)
                {
                    NetLog.Warning("SerializeReliableMessage failed.");
                    retryingSerialization = false;
                    return;
                }

                retryingSerialization = true;
                FlushStream();
                SerializeReliableMessage(message);
            }

            if (retryingSerialization)
            {
                retryingSerialization = false;
            }
        }
Пример #2
0
        private void ReceiveCreateView(NetMessage message, NetConnection server)
        {
            if (!server.IsServer && !server.IsPeer)
            {
                return;
            }

            int    viewId     = (int)message.Parameters[0];
            int    group      = (int)message.Parameters[1];
            string prefabRoot = (string)message.Parameters[2];
            var    stream     = (NetStream)message.Parameters[3];

            NetView.Relation relation   = default(NetView.Relation);
            NetConnection    controller = null;

            switch (message.MessageId)
            {
            case (int)ViewCmd.CreateOwnerView:
                controller = Socket.Self;
                relation   = NetView.Relation.Owner;
                break;

            case (int)ViewCmd.CreatePeerView:
                relation = NetView.Relation.Peer;
                break;

            case (int)ViewCmd.CreateCreatorView:
                server   = Socket.Self;
                relation = NetView.Relation.Creator;
                break;

            case (int)ViewCmd.CreateProxyView:
                relation = NetView.Relation.Proxy;
                break;
            }

            if (relation == NetView.Relation.Creator || relation == NetView.Relation.Peer)
            {
                var ipendpoint = (IPEndPoint)message.Parameters[4];
                if (ipendpoint != null)
                {
                    if (Socket.EndpointConnected(ipendpoint))
                    {
                        controller = Socket.EndpointToConnection(ipendpoint);
                    }
                    else
                    {
                        NetLog.Error("Failed to create view, controller endpoint not connected: " + ipendpoint);
                    }
                }
            }

            var view = CreateView(controller, server, viewId, group, prefabRoot, relation);

            view.TriggerReadInstantiateData(stream);
            if (OnNetViewCreated != null)
            {
                OnNetViewCreated(view);
            }
        }
Пример #3
0
        public IEnumerator SetServer(NetConnection server, NetZone zone)
        {
            zone.Assigned = true;

            if (server != Socket.Self)
            {
                var setServerRequest = Socket.Request.Send <string>("AssignZone", server, zone);

                yield return(setServerRequest.WaitUntilDone);

                if (!setServerRequest.IsSuccessful)
                {
                    zone.Assigned = false;
                    yield break;
                }

                zone.PublicEndpoint = setServerRequest.Result;
            }
            else
            {
                NetZoneServer zoneServ = GetComponent <NetZoneServer>();
                zoneServ.AssignZoneSelf(zone);
            }

            zone.Server         = server;
            zone.ServerEndpoint = zone.Server.Endpoint;
            if (string.IsNullOrEmpty(zone.PublicEndpoint))
            {
                zone.PublicEndpoint = zone.Server.Endpoint.ToString();
            }
            ZoneAssigned(zone);
            NetLog.Info("Server assigned to zone. Endpoint: " + server.Endpoint);
            zone.Available = true;
        }
Пример #4
0
        /// <summary>
        /// Sets request result and removes request from queue.
        /// </summary>
        internal void SetResponse(NetMessage message, NetConnection connection)
        {
            if (message.Parameters.Length < 2 || !(message.Parameters[0] is ushort))
            {
                NetLog.Error("Received malformed request response. Discarding.");
                return;
            }

            ushort requestId = (ushort)message.Parameters[0];
            uint   key       = CreateKey(message.ViewId, requestId);

            if (!requests.ContainsKey(key))
            {
                //NetLog.Trace("Active request doesn't exist for response. Discarding.");
                return;
            }

            object requestObj = requests[key];

            requests.Remove(key);

            if ((bool)message.Parameters[1])
            {
                MethodInfo setResponse = requestObj.GetType().GetMethod("SetResponse");
                setResponse.Invoke(requestObj, message.Parameters);
            }
            else
            {
                MethodInfo failureResponse = requestObj.GetType().GetMethod("FailureResponse", BindingFlags.NonPublic);
                failureResponse.Invoke(requestObj, null);
            }
        }
Пример #5
0
 /// <summary>
 /// When an RPC is received, the targeted NetView is identified and DispatchRPC is called for that
 /// particular NetView object. DispatchRPC then identifies the targeted method and invokes it with
 /// the supplied parameters.
 /// </summary>
 internal void DispatchRpc(string methodName, NetMessage message, NetConnection connection)
 {
     if (!CachedRpcObjects.ContainsKey(methodName))
     {
         NetLog.Error(string.Format("Can't find RPC method \"{0}\" for View {1}.", methodName, Id));
         return;
     }
     Socket.Rpc.Invoke(CachedRpcObjects[methodName], methodName, message, connection);
 }
Пример #6
0
 internal void Register(ushort commandId, Action <NetStream, NetConnection> target)
 {
     if (paramTypes.ContainsKey(commandId))
     {
         NetLog.Error("Command Id already in use. Cannot add command.");
         return;
     }
     streamTargets.Add(commandId, target);
     paramTypes.Add(commandId, streamTypes);
 }
Пример #7
0
 internal void Register(ushort commandId, Action <NetMessage, NetConnection> target, List <Type> types)
 {
     if (paramTypes.ContainsKey(commandId))
     {
         NetLog.Error("Command Id already in use. Cannot add command.");
         return;
     }
     paramTypes.Add(commandId, types);
     targets.Add(commandId, target);
 }
Пример #8
0
        /// <summary> Sends a reliable RPC that does not target a specific view. </summary>
        public void Send(string methodName, NetConnection target, params object[] parameters)
        {
            if (!Rpc.HasId(methodName))
            {
                NetLog.Error("Remote RPC does not have an assigned ID: " + methodName);
                return;
            }
            var message = NetMessage.Create(Rpc.NameToId(methodName), 0, parameters, true);

            target.Send(message);
        }
Пример #9
0
        /// <summary> Send overload that creates the NetMessage for the RPC. </summary>
        internal void Send(int viewId, bool reliable, string methodName, NetConnection target, params object[] parameters)
        {
            if (!Socket.Rpc.HasId(methodName))
            {
                NetLog.Error("Send failed: RPC method name has not been assigned an ID.");
                return;
            }
            var netMessage = NetMessage.Create(Socket.Rpc.NameToId(methodName), (uint)viewId, parameters, reliable);

            target.Send(netMessage);
        }
Пример #10
0
 private void PeerDisconnected(NetConnection connection)
 {
     NetLog.Info("ZoneManager: Peer Disconnected: " + connection.Endpoint);
     if (peers.Contains(connection))
     {
         peers.Remove(connection);
     }
     if (Authority)
     {
         RemoveServer(connection);
     }
 }
Пример #11
0
 private void ReceivePeerConnectionRequest(IPEndPoint endpoint, NetStream readStream)
 {
     if (!AcceptConnections || Connections.Count >= MaxConnections || !Events.PeerApproval(endpoint, readStream))
     {
         NetLog.Info("Refused peer connection: " + endpoint);
         TrySend(new[] { (byte)ByteCmd.RefuseConnection }, 1, endpoint);
     }
     else
     {
         CreateConnection(endpoint, false, true);
     }
 }
Пример #12
0
        /// <summary>
        /// Passes parameters from an incoming network message to the method associated with the RPC.
        /// </summary>
        internal void DispatchRpc(NetMessage message, NetConnection connection)
        {
            string methodName = Rpc.IdToName(message.MessageId);

            if (!rpcObjectInstances.ContainsKey(methodName))
            {
                NetLog.Error(string.Format("Can't find method \"{0}\" for Viewless RPC.", methodName));
                return;
            }

            Rpc.Invoke(rpcObjectInstances[methodName], methodName, message, connection);
        }
Пример #13
0
 internal void RegisterParams(ushort commandId, List <Type> paramTypes)
 {
     if (this.paramTypes.ContainsKey(commandId))
     {
         NetLog.Error("Command Id already in use. Cannot add command types.");
         return;
     }
     if (commandId < 1800 || commandId > 2047)
     {
         throw new Exception("Cannot register Command - Range: 1800-2047 - Provided: " + commandId);
     }
     this.paramTypes.Add(commandId, paramTypes);
 }
Пример #14
0
 internal void AssignZoneSelf(NetZone zone)
 {
     if (ViewManager.GenerateViewId == null)
     {
         ViewManager.GenerateViewId += AllocateViewId;
     }
     NetLog.Info("Assigned to zone.");
     self = zone;
     if (OnAssignment != null)
     {
         OnAssignment();
     }
 }
Пример #15
0
        /// <summary>
        ///  Returns the connection that matches the supplied target.
        ///  Returns the server for Server or the first controller for Controllers.
        /// </summary>
        internal NetConnection GetTarget(RpcTarget target, NetView view)
        {
            switch (target)
            {
            case RpcTarget.Server:
                return(view.Server);

            case RpcTarget.Controllers:
                return(view.Controllers[0]);
            }

            NetLog.Error("Invalid RpcTarget for GetTarget. Only RpcTarget.Server or RpcTarget.Controllers can be used.");
            return(null);
        }
Пример #16
0
        internal static NetMessage ReadNetMessage(NetStream stream)
        {
            List <Type> paramTypes;
            ushort      messageId = stream.ReadUShort(11);
            uint        viewId    = 0;

            if (stream.ReadBool())
            {
                viewId = stream.ReadUInt(20);
            }

            if (messageId == (int)Cmd.RequestResponse)
            {
                return(CreateResponseMessage(stream, messageId, viewId));
            }

            if (messageId > 1800)
            {
                if (!stream.Socket.Command.Exists(messageId))
                {
                    NetLog.Error("Cannot deserialize message, Command ID not found: " + messageId);
                    return(null);
                }
                paramTypes = stream.Socket.Command.ParamTypes(messageId);
            }
            else
            {
                if (!stream.Socket.Rpc.Exists(messageId))
                {
                    NetLog.Error("Cannot deserialize message, RPC ID not found: " + messageId);
                    return(null);
                }
                paramTypes = stream.Socket.Rpc.ParamTypes(messageId);
            }

            NetMessage netMessage = NetMessage.Create(messageId, viewId, paramTypes.Count, false);

            if (stream.Socket.Rpc.TakesRequests(messageId))
            {
                return(CreateRequestMessage(stream, netMessage, paramTypes));
            }

            for (int i = 0; i < paramTypes.Count; i++)
            {
                netMessage.Parameters[i] = ReadParam(stream, paramTypes[i]);
            }

            return(netMessage);
        }
Пример #17
0
        private void PeerConnected(NetConnection connection)
        {
            if (!peerLookup.ContainsKey(connection.Endpoint))
            {
                return;
            }
            NetZone peer = peerLookup[connection.Endpoint];

            NetLog.Info("Connection is Zone Peer: " + peer);
            peer.Server = connection;
            connection.InternalScope              = new NetScope();
            connection.InternalScope.Position     = peer.Position;
            connection.InternalScope.OutScopeDist = (int)(peer.HandoverMaxDistance * 1.25);
            connection.InternalScope.InScopeDist  = peer.HandoverMaxDistance;
        }
Пример #18
0
        /// <summary> Send overload that creates the NetMessage for the RPC. </summary>
        internal void Send(int viewId, bool reliable, string methodName, List <NetConnection> targets, params object[] parameters)
        {
            if (!Socket.Rpc.HasId(methodName))
            {
                NetLog.Error("Send failed: RPC method name has not been assigned an ID.");
                return;
            }

            var message = NetMessage.Create(Socket.Rpc.NameToId(methodName), (uint)viewId, parameters, reliable);

            for (int i = 0; i < targets.Count; i++)
            {
                targets[i].Send(message);
            }
        }
Пример #19
0
 /// <summary> Sends a message to this connection. </summary>
 internal void Send(NetMessage message)
 {
     if (this == Socket.Self)
     {
         NetLog.Warning("Trying to send message to self.");
     }
     if (!message.Reliable)
     {
         Unreliable.SerializeMessage(message);
     }
     else
     {
         Reliable.SerializeReliableMessage(message);
     }
 }
Пример #20
0
        /// <summary> Adds a new NetConnection to the connection list. </summary>
        internal NetConnection CreateConnection(IPEndPoint ep, bool isServer, bool isPeer)
        {
            bool wasServer = false;

            // Connection cannot be both server and peer:
            if (isPeer)
            {
                isServer  = false;
                wasServer = true;
            }

            var connection = new NetConnection(isServer, isPeer, this, ep);

            Connections.Add(connection);
            endpointToConnection.Add(ep, connection);
            if (isPeer)
            {
                NetLog.Info("Peer connection created: " + ep);
            }
            else if (isServer)
            {
                NetLog.Info("Server connection created: " + ep);
            }
            else
            {
                NetLog.Info("Client connection created: " + ep);
            }

            if (ProtocolAuthority && !isServer && !wasServer)
            {
                SendConnectionRequirements(connection);
                Rpc.SendLocalAssignments(connection);
            }
            else if (connection.IsPeer && Rpc.IdCount == RpcInfoCache.Count)
            {
                Events.PeerConnected(connection);
            }
            else if (isServer && Rpc.IdCount == RpcInfoCache.Count)
            {
                Events.ConnectedToServer(connection);
            }
            else if (!isServer && !isPeer)
            {
                Events.ClientConnected(connection);
            }

            return(connection);
        }
Пример #21
0
        /// <summary> Send overload that creates the NetMessage for the RPC. </summary>
        internal void Send(int viewId, bool reliable, string methodName, RpcTarget target, params object[] parameters)
        {
            if (!Socket.Rpc.HasId(methodName))
            {
                NetLog.Error("Send failed: RPC method name has not been assigned an ID.");
                return;
            }
            if (!ViewLookup.ContainsKey(viewId))
            {
                return;
            }
            NetView view       = ViewLookup[viewId];
            var     netMessage = NetMessage.Create(Socket.Rpc.NameToId(methodName), (uint)viewId, parameters, reliable);

            Send(view, netMessage, target);
        }
Пример #22
0
        private void ReceiveConnectionResponse(IPEndPoint endpoint, int bytesReceived, NetStream readStream)
        {
            bool isPeer = RemoveFromConnecting(endpoint, true);

            if (bytesReceived == 1 && readStream.Data[0] == (byte)ByteCmd.RefuseConnection)
            {
                NetLog.Info("Connection refused by: " + endpoint);
                return;
            }
            var connection = CreateConnection(endpoint, true, isPeer);

            if (bytesReceived > 1)
            {
                connection.ReceiveStream(readStream);
            }
        }
Пример #23
0
        /// <summary>
        /// Starts the socket using the supplied endpoint.
        /// If the port is taken, the given port will be incremented to a free port.
        /// </summary>
        public void StartSocket(IPEndPoint endpoint)
        {
            Self   = new NetConnection(false, false, this, endpoint);
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            try {
                const uint IOC_IN            = 0x80000000;
                const uint IOC_VENDOR        = 0x18000000;
                uint       SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
                socket.IOControl((int)SIO_UDP_CONNRESET, new[] { Convert.ToByte(false) }, null);
            } catch {
                NetLog.Warning("Failed to set control code for ignoring ICMP port unreachable.");
            }

            socket.ReceiveBufferSize = 4194304;
            if (socket.ReceiveBufferSize != 4194304)
            {
                NetLog.Warning("ReceiveBufferSize restricted by OS.");
            }
            socket.SendBufferSize = 1048576;
            socket.Blocking       = false;

            try {
                socket.Bind(endpoint);
            } catch (SocketException e) {
                if (e.ErrorCode == 10048)
                {
                    var newEp = new IPEndPoint(endpoint.Address, endpoint.Port + 1);
                    NetLog.Warning("Port in use. Incrementing and retrying...");
                    StartSocket(newEp);
                }
                else
                {
                    NetLog.Error(e.Message);
                }
                return;
            }

            NetLog.Info(NetTime.StartDateTime() + " | Socket Started. Bound to: " + endpoint);
            NetTime.Milliseconds();

            if (ProtocolAuthority)
            {
                Rpc.AssignLocalRpcs();
            }
            Events.SocketStart();
        }
Пример #24
0
 /// <summary> Performs end-frame tasks such as flushing stream & checking timeouts. </summary>
 internal void EndOfFrame(uint currentTime)
 {
     if (ShouldDisconnect(currentTime))
     {
         NetLog.Info("Disconnecting connection due to overflow or timeout: " + Endpoint);
         Disconnect();
         return;
     }
     if (!Reliable.FlushStream() && Reliable.ShouldForceAck(currentTime))
     {
         Reliable.ForceAck();
     }
     if (!Unreliable.FlushStream() && ShouldSendHeartbeat(currentTime))
     {
         Unreliable.SendHeartbeat();
     }
     Reliable.CheckTimeouts(currentTime);
 }
Пример #25
0
        private void DeliverSyncStream(NetMessage message, NetConnection connection)
        {
            if (!ViewLookup.ContainsKey((int)message.ViewId))
            {
                return;
            }
            var view = ViewLookup[(int)message.ViewId];

            if (!view.IsController(connection) && connection != view.Server)
            {
                if (!connection.IsServer)
                {
                    NetLog.Warning("Connection attempting to send to unauthorized View: " + connection.Endpoint);
                    return;
                }
                view.Server = connection;
            }
            view.TriggerReadSync((NetStream)message.Parameters[0]);
        }
Пример #26
0
 /// <summary> Deserializes incoming reliable stream into NetMessages, forwards them to the NetSocket, releases the stream,
 /// increments the remote sequence, and retries the out-of-order buffer when needed. </summary>
 private void DeliverStream(NetStream strm)
 {
     // Deserialize stream into individual messages and pass them to the socket:
     while (NetSerializer.CanReadMessage(strm))
     {
         var message = NetSerializer.ReadNetMessage(strm);
         if (message == null)
         {
             NetLog.Error("Failed to parse reliable message from: " + Connection.Endpoint + " Pos: " + strm.Pos + " Size: " + strm.Size);
             break;
         }
         Connection.Socket.ReceiveMessage(message, Connection);
     }
     // Return stream to pool and update receive buffer distances:
     strm.Release();
     LastAcceptedRemoteSequence++;
     if (recvBuffer.Count > 0)
     {
         DecrementReceiveBuffer();
     }
 }
Пример #27
0
        private void ReceiveMessage(NetMessage message, NetConnection connection)
        {
            if (!ViewLookup.ContainsKey((int)message.ViewId))
            {
                return;
            }

            string methodName = Socket.Rpc.IdToName(message.MessageId);
            var    view       = ViewLookup[(int)message.ViewId];

            if (!view.IsController(connection) && connection != view.Server)
            {
                if (!connection.IsServer)
                {
                    NetLog.Warning("Connection attempting to send to unauthorized View: " + connection.Endpoint);
                    return;
                }
                view.Server = connection;
            }
            view.DispatchRpc(methodName, message, connection);
        }
Пример #28
0
        internal void RemovePeerSelf(NetZone zone)
        {
            NetLog.Info("Removing zone");

            if (peerLookup.ContainsKey(zone.ServerEndpoint))
            {
                peerLookup.Remove(zone.ServerEndpoint);
            }
            else if (peerLookup.ContainsValue(zone))
            {
                NetLog.Warning("RemovePeer: Zone endpoint mismatch.");
            }

            if (peers.Contains(zone))
            {
                peers.Remove(zone);
            }
            else
            {
                NetLog.Info("RemovePeer: Zone not in peer list.");
            }
        }
Пример #29
0
        /// <summary> Cleans up a connection attempt and returns true if it is a peer connection. </summary>
        internal bool RemoveFromConnecting(IPEndPoint ep, bool successful)
        {
            bool isPeer = false;

            if (!successful)
            {
                NetLog.Info("Failed to connect to: " + ep);
                Events.FailedToConnect(ep);
            }
            int index = connectingEndpoints.IndexOf(ep);

            connectingTimes.RemoveAt(index);
            connectingRetriesRemaining.RemoveAt(index);
            connectingEndpoints.Remove(ep);
            if (connectingData[index].Data[0] == (byte)ByteCmd.ConnectToPeer)
            {
                isPeer = true;
            }
            connectingData[index].Release();
            connectingData.RemoveAt(index);
            return(isPeer);
        }
Пример #30
0
        /// <summary> Sends an RPC to connections that are in-scope for the provided view. </summary>
        internal void Send(NetView view, NetMessage netMessage, RpcTarget target)
        {
            switch (target)
            {
            case (RpcTarget.All):
                for (int i = 0; i < Socket.Connections.Count; i++)
                {
                    var connection = Socket.Connections[i];
                    if (!connection.HasScope)
                    {
                        continue;
                    }
                    if (view.Group != 0 && !connection.InGroup(view.Group))
                    {
                        continue;
                    }
                    if ((netMessage.Reliable && connection.Scope.In(view.Id)) || connection.Scope.In(view.Id, syncFrame) || view.IsController(connection))
                    {
                        connection.Send(netMessage);
                    }
                }
                break;

            case (RpcTarget.Controllers):
                foreach (NetConnection controller in view.Controllers)
                {
                    if (controller == Socket.Self)
                    {
                        continue;
                    }
                    controller.Send(netMessage);
                }
                break;

            case (RpcTarget.NonControllers):
                for (int i = 0; i < Socket.Connections.Count; i++)
                {
                    var connection = Socket.Connections[i];
                    if (connection.IsServer || !connection.HasScope)
                    {
                        continue;
                    }
                    if (view.IsController(connection))
                    {
                        continue;
                    }
                    if (view.Group != 0 && !connection.InGroup(view.Group))
                    {
                        continue;
                    }
                    if ((netMessage.Reliable && connection.Scope.In(view.Id)) || connection.Scope.In(view.Id, syncFrame))
                    {
                        connection.Send(netMessage);
                    }
                }
                break;

            case (RpcTarget.Server):
                if (view.Server != Socket.Self)
                {
                    view.Server.Send(netMessage);
                }
                else
                {
                    NetLog.Warning("Trying to send message to self.");
                }
                break;

            case (RpcTarget.AllInclOutOfScope):
                for (int i = 0; i < Socket.Connections.Count; i++)
                {
                    var connection = Socket.Connections[i];
                    if (view.Group != 0 && !connection.InGroup(view.Group))
                    {
                        continue;
                    }
                    connection.Send(netMessage);
                }
                break;
            }
        }