internal static BitStream WrapMessage(byte messageType, ulong clientID, BitStream messageBody, SecuritySendFlags flags)
        {
            try
            {
                bool encrypted     = ((flags & SecuritySendFlags.Encrypted) == SecuritySendFlags.Encrypted) && false;             //NetworkManager.Get().NetworkConfig.EnableEncryption;
                bool authenticated = (flags & SecuritySendFlags.Authenticated) == SecuritySendFlags.Authenticated && false;       //NetworkManager.Get().NetworkConfig.EnableEncryption;

                PooledBitStream outStream = PooledBitStream.Get();

                using (PooledBitWriter outWriter = PooledBitWriter.Get(outStream))
                {
                    outWriter.WriteBit(encrypted);
                    outWriter.WriteBit(authenticated);
                    outWriter.WriteBits(messageType, 6);
                    outStream.Write(messageBody.GetBuffer(), 0, (int)messageBody.Length);
                }

                return(outStream);
            }
            catch (Exception e)
            {
                Debug.LogError("Error while wrapping headers");
                Debug.LogError(e.ToString());

                return(null);
            }
        }
Beispiel #2
0
        internal static void WriteSpawnCallForObject(MLAPI.Serialization.BitStream stream, ulong clientId, NetworkedObject netObject, Stream payload)
        {
            using (PooledBitWriter writer = PooledBitWriter.Get(stream))
            {
                writer.WriteBool(netObject.IsPlayerObject);
                writer.WriteUInt64Packed(netObject.NetworkId);
                writer.WriteUInt64Packed(netObject.OwnerClientId);

                if (NetworkingManager.Singleton.NetworkConfig.UsePrefabSync)
                {
                    writer.WriteUInt64Packed(netObject.PrefabHash);
                }
                else
                {
                    writer.WriteBool(netObject.IsSceneObject == null ? true : netObject.IsSceneObject.Value);

                    if (netObject.IsSceneObject == null || netObject.IsSceneObject.Value)
                    {
                        writer.WriteUInt64Packed(netObject.NetworkedInstanceId);
                    }
                    else
                    {
                        writer.WriteUInt64Packed(netObject.PrefabHash);
                    }
                }

                writer.WriteSinglePacked(netObject.transform.position.x);
                writer.WriteSinglePacked(netObject.transform.position.y);
                writer.WriteSinglePacked(netObject.transform.position.z);

                writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.x);
                writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.y);
                writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.z);

                writer.WriteBool(payload != null);

                if (payload != null)
                {
                    writer.WriteInt32Packed((int)payload.Length);
                }

                if (NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar)
                {
                    netObject.WriteNetworkedVarData(stream, clientId);
                }

                if (payload != null)
                {
                    stream.CopyFrom(payload);
                }
            }
        }
            public byte[] ToBytes()
            {
                BitStream stream = new BitStream();
                BitWriter writer = new BitWriter(stream);

                writer.WriteUInt16Packed((ushort)ticks.Length);

                for (int i = 0; i < ticks.Length; i++)
                {
                    ticks[i].SerializeToStream(stream);
                }

                return(stream.ToArray());
            }
Beispiel #4
0
        /// <summary>
        /// Handle the valid messages received from NetworkManager.HandleIncomingData().
        /// </summary>
        /// <param name="sendingClientID"></param>
        /// <param name="messageType"></param>
        /// <param name="messageStream"></param>
        /// <param name="receiveTime"></param>
        public void HandleMessage(ulong sendingClientID, byte messageType, BitStream messageStream, float receiveTime)
        {
            if (messageType >= m_FirstFreeIndex)
            {
                if (messageType == (byte)MessageType.INVALID)
                {
                    Debug.LogWarning("Received invalid message.");
                    return;
                }

                Debug.LogError("Received unknown message type. Message type: " + messageType.ToString());
                return;
            }

            NetworkMessageReceiver receiver = m_Receivers[messageType];

            switch (receiver)
            {
            case NetworkMessageReceiver.Both:
                m_Callbacks[messageType].Invoke(sendingClientID, messageStream, receiveTime);
                break;

            case NetworkMessageReceiver.Client:
                if (networkManager.isClient)
                {
                    m_Callbacks[messageType].Invoke(sendingClientID, messageStream, receiveTime);
                }
#if DEVELOPMENT_BUILD || UNITY_EDITOR
                if (!networkManager.isClient)
                {
                    Debug.LogError("Client '" + sendingClientID + "' sent message type " + GetMessageName(messageType) + "(" + messageType.ToString() + ") when the Network Message Receiver for this message type is set to Client.");
                }
#endif
                break;

            case NetworkMessageReceiver.Server:
                if (networkManager.isServer)
                {
                    m_Callbacks[messageType].Invoke(sendingClientID, messageStream, receiveTime);
                }
#if DEVELOPMENT_BUILD || UNITY_EDITOR
                if (!networkManager.isServer)
                {
                    Debug.LogError("Server sent message type '" + GetMessageName(messageType) + "(" + messageType.ToString() + ")' when the Network Message Receiver for this message type is set to Server.");
                }
#endif
                break;
            }
        }
        // This method is responsible for unwrapping a message, that is extracting the messagebody.
        // Could include decrypting and/or authentication.
        internal static BitStream UnwrapMessage(BitStream inputStream, ulong clientID, out byte messageType, out SecuritySendFlags security)
        {
            using (PooledBitReader inputHeaderReader = PooledBitReader.Get(inputStream))
            {
                try
                {
                    if (inputStream.Length < 1)
                    {
                        Debug.LogError("The incoming message was too small");
                        messageType = (byte)MessageType.INVALID;
                        security    = SecuritySendFlags.None;
                        return(null);
                    }

                    bool isEncrypted     = inputHeaderReader.ReadBit();
                    bool isAuthenticated = inputHeaderReader.ReadBit();

                    if (isEncrypted && isAuthenticated)
                    {
                        security = SecuritySendFlags.Encrypted | SecuritySendFlags.Authenticated;
                    }
                    else if (isEncrypted)
                    {
                        security = SecuritySendFlags.Encrypted;
                    }
                    else if (isAuthenticated)
                    {
                        security = SecuritySendFlags.Authenticated;
                    }
                    else
                    {
                        security = SecuritySendFlags.None;
                    }

                    messageType = inputHeaderReader.ReadByteBits(6);
                    // The input stream is now ready to be read from. It's "safe" and has the correct position
                    return(inputStream);
                }
                catch (Exception e)
                {
                    Debug.LogError("Error while unwrapping headers");
                    Debug.LogError(e.ToString());

                    security    = SecuritySendFlags.None;
                    messageType = (byte)MessageType.INVALID;
                    return(null);
                }
            }
        }
            public static ProfilerContainer FromBytes(byte[] bytes)
            {
                ProfilerContainer container = new ProfilerContainer();
                BitStream         stream    = new BitStream(bytes);
                BitReader         reader    = new BitReader(stream);
                ushort            count     = reader.ReadUInt16Packed();

                container.ticks = new ProfilerTick[count];
                for (int i = 0; i < count; i++)
                {
                    container.ticks[i] = ProfilerTick.FromStream(stream);
                }

                return(container);
            }
Beispiel #7
0
        private void HandleIncomingData(ulong sendingClientID, byte channel, ArraySegment <byte> data, float receiveTime)
        {
            if (enableLogging)
            {
                Debug.Log("Unwrapping Data Header");
            }

            inputStreamWrapper.SetTarget(data.Array);
            inputStreamWrapper.SetLength(data.Count + data.Offset);
            inputStreamWrapper.Position = data.Offset;

            using (BitStream messageStream = MessagePacker.UnwrapMessage(inputStreamWrapper, sendingClientID, out byte messageType, out SecuritySendFlags security))
            {
                if (messageStream == null)
                {
                    Debug.LogError("Message unwrap could not be completed. Was the header corrupt? Crypto error?");
                    return;
                }
                else if (messageType == (byte)MessageType.INVALID)
                {
                    Debug.LogError("Message unwrap read an invalid messageType");
                    return;
                }

                uint headerByteSize = (uint)Arithmetic.VarIntSize(messageType);

                //if(enableLogging)
                //Debug.Log("Data Header: messageType=" + m_MessageHandler.GetMessageName(messageType) + "(" + messageType + ")");

                // Client tried to send a network message that was not the connection request before they were accepted
                if (m_PendingClientsDictionary.ContainsKey(sendingClientID) && m_PendingClientsDictionary[sendingClientID].connectionState == PendingClient.State.PendingConnection && messageType != (byte)MessageType.NETWORK_CONNECTION_REQUEST)
                {
                    Debug.LogWarning("Message received from clientID " + sendingClientID + " before it has been accepted. Message type: (" + messageType.ToString() + ") " + m_MessageHandler.GetMessageName(messageType));
                    return;
                }

                //Handle Message
                m_MessageHandler.HandleMessage(sendingClientID, messageType, messageStream, receiveTime);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Sets the NetworkConfig data with that from a base64 encoded version
        /// </summary>
        /// <param name="base64">The base64 encoded version</param>
        public void FromBase64(string base64)
        {
            NetworkConfig config = this;

            byte[] binary = Convert.FromBase64String(base64);
            using (BitStream stream = new BitStream(binary))
            {
                using (PooledBitReader reader = PooledBitReader.Get(stream))
                {
                    config.ProtocolVersion = reader.ReadUInt16Packed();

                    ushort sceneCount = reader.ReadUInt16Packed();
                    config.RegisteredScenes.Clear();

                    for (int i = 0; i < sceneCount; i++)
                    {
                        config.RegisteredScenes.Add(reader.ReadString().ToString());
                    }

                    config.ReceiveTickrate             = reader.ReadInt32Packed();
                    config.MaxReceiveEventsPerTickRate = reader.ReadInt32Packed();
                    config.SendTickrate  = reader.ReadInt32Packed();
                    config.EventTickrate = reader.ReadInt32Packed();
                    config.ClientConnectionBufferTimeout = reader.ReadInt32Packed();
                    config.ConnectionApproval            = reader.ReadBool();
                    config.SecondsHistory     = reader.ReadInt32Packed();
                    config.EnableEncryption   = reader.ReadBool();
                    config.SignKeyExchange    = reader.ReadBool();
                    config.LoadSceneTimeOut   = reader.ReadInt32Packed();
                    config.EnableTimeResync   = reader.ReadBool();
                    config.RpcHashSize        = (HashSize)reader.ReadBits(3);
                    config.ForceSamePrefabs   = reader.ReadBool();
                    config.UsePrefabSync      = reader.ReadBool();
                    config.EnableNetworkedVar = reader.ReadBool();
                }
            }
        }
Beispiel #9
0
        internal static NetworkedObject CreateSpawnedObject(int networkedPrefabId, uint networkId, uint owner, bool playerObject, uint sceneSpawnedInIndex, bool sceneDelayedSpawn, bool destroyWithScene, Vector3?position, Quaternion?rotation, bool isActive, Stream stream, bool readPayload, int payloadLength, bool readNetworkedVar)
        {
            if (networkedPrefabId >= netManager.NetworkConfig.NetworkedPrefabs.Count || networkedPrefabId < 0)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Cannot spawn the object, invalid prefabIndex: " + networkedPrefabId);
                }
                return(null);
            }

            //Delayed spawning
            if (sceneDelayedSpawn && sceneSpawnedInIndex != NetworkSceneManager.CurrentActiveSceneIndex)
            {
                GameObject prefab       = netManager.NetworkConfig.NetworkedPrefabs[networkedPrefabId].prefab;
                bool       prefabActive = prefab.activeSelf;
                prefab.SetActive(false);
                GameObject go = (position == null && rotation == null) ? MonoBehaviour.Instantiate(prefab) : MonoBehaviour.Instantiate(prefab, position.GetValueOrDefault(Vector3.zero), rotation.GetValueOrDefault(Quaternion.identity));
                prefab.SetActive(prefabActive);

                //Appearantly some wierd behavior when switching scenes can occur that destroys this object even though the scene is
                //not destroyed, therefor we set it to DontDestroyOnLoad here, to prevent that problem.
                MonoBehaviour.DontDestroyOnLoad(go);

                NetworkedObject netObject = go.GetComponent <NetworkedObject>();
                if (netObject == null)
                {
                    if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                    {
                        LogHelper.LogWarning("Please add a NetworkedObject component to the root of all spawnable objects");
                    }
                    netObject = go.AddComponent <NetworkedObject>();
                }

                netObject.NetworkedPrefabName = netManager.NetworkConfig.NetworkedPrefabs[networkedPrefabId].name;
                netObject.isSpawned           = false;
                netObject.isPooledObject      = false;

                if (netManager.isServer)
                {
                    netObject.NetworkId = GetNetworkObjectId();
                }
                else
                {
                    netObject.NetworkId = networkId;
                }

                netObject.destroyWithScene    = destroyWithScene;
                netObject.OwnerClientId       = owner;
                netObject.isPlayerObject      = playerObject;
                netObject.SceneDelayedSpawn   = sceneDelayedSpawn;
                netObject.sceneSpawnedInIndex = sceneSpawnedInIndex;

                Dictionary <ushort, List <INetworkedVar> > dummyNetworkedVars = new Dictionary <ushort, List <INetworkedVar> >();
                List <NetworkedBehaviour> networkedBehaviours = new List <NetworkedBehaviour>(netObject.GetComponentsInChildren <NetworkedBehaviour>());
                for (ushort i = 0; i < networkedBehaviours.Count; i++)
                {
                    dummyNetworkedVars.Add(i, networkedBehaviours[i].GetDummyNetworkedVars());
                }

                PendingSpawnObject pso = new PendingSpawnObject()
                {
                    netObject           = netObject,
                    dummyNetworkedVars  = dummyNetworkedVars,
                    sceneSpawnedInIndex = sceneSpawnedInIndex,
                    playerObject        = playerObject,
                    owner    = owner,
                    isActive = isActive,
                    payload  = null
                };
                PendingSpawnObjects.Add(netObject.NetworkId, pso);

                pso.SetNetworkedVarData(stream);
                if (readPayload)
                {
                    MLAPI.Serialization.BitStream payloadStream = new MLAPI.Serialization.BitStream();
                    payloadStream.CopyUnreadFrom(stream, payloadLength);
                    stream.Position += payloadLength;
                    pso.payload      = payloadStream;
                }

                return(netObject);
            }

            //Normal spawning
            {
                GameObject prefab = netManager.NetworkConfig.NetworkedPrefabs[networkedPrefabId].prefab;
                GameObject go     = (position == null && rotation == null) ? MonoBehaviour.Instantiate(prefab) : MonoBehaviour.Instantiate(prefab, position.GetValueOrDefault(Vector3.zero), rotation.GetValueOrDefault(Quaternion.identity));

                NetworkedObject netObject = go.GetComponent <NetworkedObject>();
                if (netObject == null)
                {
                    if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                    {
                        LogHelper.LogWarning("Please add a NetworkedObject component to the root of all spawnable objects");
                    }
                    netObject = go.AddComponent <NetworkedObject>();
                }

                if (readNetworkedVar)
                {
                    netObject.SetNetworkedVarData(stream);
                }

                netObject.NetworkedPrefabName = netManager.NetworkConfig.NetworkedPrefabs[networkedPrefabId].name;
                netObject.isSpawned           = true;
                netObject.isPooledObject      = false;

                if (netManager.isServer)
                {
                    netObject.NetworkId = GetNetworkObjectId();
                }
                else
                {
                    netObject.NetworkId = networkId;
                }

                netObject.destroyWithScene    = destroyWithScene;
                netObject.OwnerClientId       = owner;
                netObject.isPlayerObject      = playerObject;
                netObject.SceneDelayedSpawn   = sceneDelayedSpawn;
                netObject.sceneSpawnedInIndex = sceneSpawnedInIndex;

                SpawnedObjects.Add(netObject.NetworkId, netObject);
                SpawnedObjectsList.Add(netObject);
                if (playerObject)
                {
                    NetworkingManager.singleton.ConnectedClients[owner].PlayerObject = netObject;
                }

                if (readPayload)
                {
                    using (PooledBitStream payloadStream = PooledBitStream.Get())
                    {
                        payloadStream.CopyUnreadFrom(stream, payloadLength);
                        stream.Position += payloadLength;
                        netObject.InvokeBehaviourNetworkSpawn(payloadStream);
                    }
                }
                else
                {
                    netObject.InvokeBehaviourNetworkSpawn(null);
                }

                netObject.gameObject.SetActive(isActive);
                return(netObject);
            }
        }
Beispiel #10
0
        /// <summary>
        /// Sets the NetworkConfig data with that from a base64 encoded version
        /// </summary>
        /// <param name="base64">The base64 encoded version</param>
        /// <param name="createDummyObject">Wheter or not to create dummy objects for NetworkedPrefabs</param>
        public void FromBase64(string base64, bool createDummyObject = false)
        {
            NetworkConfig config = this;

            byte[] binary = Convert.FromBase64String(base64);
            using (BitStream stream = new BitStream(binary))
            {
                using (PooledBitReader reader = PooledBitReader.Get(stream))
                {
                    config.ProtocolVersion = reader.ReadUInt16Packed();
                    config.Transport       = (DefaultTransport)reader.ReadBits(5);

                    ushort channelCount = reader.ReadUInt16Packed();
                    config.Channels.Clear();
                    for (int i = 0; i < channelCount; i++)
                    {
                        Channel channel = new Channel()
                        {
                            Name = reader.ReadString().ToString(),
                            Type = (ChannelType)reader.ReadBits(5)
                        };
                        config.Channels.Add(channel);
                    }

                    ushort sceneCount = reader.ReadUInt16Packed();
                    config.RegisteredScenes.Clear();
                    for (int i = 0; i < sceneCount; i++)
                    {
                        config.RegisteredScenes.Add(reader.ReadString().ToString());
                    }

                    ushort networkedPrefabsCount = reader.ReadUInt16Packed();
                    config.NetworkedPrefabs.Clear();
                    GameObject root = createDummyObject ? new GameObject("MLAPI: Dummy prefabs") : null;
                    for (int i = 0; i < networkedPrefabsCount; i++)
                    {
                        bool       playerPrefab = reader.ReadBool();
                        string     prefabName   = reader.ReadString().ToString();
                        GameObject dummyPrefab  = createDummyObject ? new GameObject("REPLACEME: " + prefabName + "(Dummy prefab)", typeof(NetworkedObject)) : null;
                        if (dummyPrefab != null)
                        {
                            dummyPrefab.GetComponent <NetworkedObject>().NetworkedPrefabName = prefabName;
                            dummyPrefab.transform.SetParent(root.transform); //This is just here to not ruin your hierarchy
                        }
                        NetworkedPrefab networkedPrefab = new NetworkedPrefab()
                        {
                            playerPrefab = playerPrefab,
                            prefab       = dummyPrefab
                        };
                        config.NetworkedPrefabs.Add(networkedPrefab);
                    }

                    config.MessageBufferSize           = reader.ReadInt32Packed();
                    config.ReceiveTickrate             = reader.ReadInt32Packed();
                    config.MaxReceiveEventsPerTickRate = reader.ReadInt32Packed();
                    config.SendTickrate   = reader.ReadInt32Packed();
                    config.EventTickrate  = reader.ReadInt32Packed();
                    config.MaxConnections = reader.ReadInt32Packed();
                    config.ConnectPort    = reader.ReadInt32Packed();
                    config.ConnectAddress = reader.ReadString().ToString();
                    config.ClientConnectionBufferTimeout = reader.ReadInt32Packed();
                    config.ConnectionApproval            = reader.ReadBool();
                    config.SecondsHistory       = reader.ReadInt32Packed();
                    config.HandleObjectSpawning = reader.ReadBool();
                    config.EnableEncryption     = reader.ReadBool();
                    config.SignKeyExchange      = reader.ReadBool();
                    config.EnableSceneSwitching = reader.ReadBool();
                    config.EnableTimeResync     = reader.ReadBool();
                    config.AttributeMessageMode = (AttributeMessageMode)reader.ReadBits(3);
                }
            }
        }