Example #1
0
        public override void Receive(byte[] data, int startIndex, int length)
        {
            //UnityEngine.Debug.LogError("Receive: " + GetType().ToString() + ": " + DeBox.Teleport.Debugging.TeleportDebugUtils.DebugString(data, startIndex, length));
            var expectedDataSize = BitConverter.ToUInt16(data, startIndex);

            startIndex += sizeof(ushort);
            length      = length - sizeof(ushort);
            var receivedDataSize = length;

            if (_receiveLeftoversLength > 0)
            {
                Array.Copy(data, startIndex, _receiveLeftovers, _receiveLeftoversLength, receivedDataSize);
                data = _receiveLeftovers;
                _receiveLeftoversLength = _receiveLeftoversLength + receivedDataSize;
                receivedDataSize        = _receiveLeftoversLength;
                UnityEngine.Debug.LogError("Had leftovers");
                startIndex = 0;
                length     = _receiveLeftoversLength;
            }
            if (expectedDataSize > receivedDataSize)
            {
                Array.Copy(data, startIndex, _receiveLeftovers, 0, receivedDataSize);
                _receiveLeftoversLength = receivedDataSize;
                UnityEngine.Debug.LogError("Not enough data! expected: " + expectedDataSize + " got: " + receivedDataSize);
                return;
            }
            else if (expectedDataSize < receivedDataSize)
            {
                _receiveLeftoversLength = receivedDataSize - expectedDataSize;
                Array.Copy(data, startIndex + expectedDataSize, _receiveLeftovers, 0, _receiveLeftoversLength);
                length = expectedDataSize;
            }
            InternalChannel.Receive(data, startIndex, length);
        }
Example #2
0
        public override byte[] PrepareToSend(byte[] data)
        {
            data = InternalChannel.PrepareToSend(data);
            var header   = BitConverter.GetBytes((ushort)data.Length);
            var fullData = new byte[header.Length + data.Length];

            Array.Copy(header, 0, fullData, 0, header.Length);
            Array.Copy(data, 0, fullData, header.Length, data.Length);
            //UnityEngine.Debug.LogError("Prepare: " + GetType().ToString() + ": " + DeBox.Teleport.Debugging.TeleportDebugUtils.DebugString(fullData));
            return(fullData);
        }
Example #3
0
        public override void Upkeep()
        {
            InternalChannel.Upkeep();
            int    maxAcks = 1;
            ushort sequenceNumber;

            while (_pendingAcksQueue.Count > 0 && maxAcks > 0)
            {
                maxAcks--;
                sequenceNumber = _pendingAcksQueue.Dequeue();
                byte[] ackData = new byte[] { 0xff, 0xff, 0, 0 };
                Array.Copy(BitConverter.GetBytes(sequenceNumber), 0, ackData, 2, 2);
                Send(ackData);
            }
        }
Example #4
0
        private void ProcessInbox()
        {
            if (_inbox.Count == 0)
            {
                return;
            }
            InboxItem inboxItem;
            ushort    nextIndex;

            while (_lastReceiveIndex > _lastProcessedReceiveIndex)
            {
                nextIndex = (ushort)(_lastProcessedReceiveIndex + 1);
                if (!_inbox.TryGetValue(nextIndex, out inboxItem))
                {
                    break;
                }

                InternalChannel.Receive(inboxItem.data, inboxItem.startIndex, inboxItem.length);
                _lastProcessedReceiveIndex = nextIndex;
            }
        }
Example #5
0
        public static void RemoveClientFromChannel(ConnectedClient ws, string channel)
        {
            if (!ws.Channels.Contains(channel))
            {
                return;
            }
            InternalChannel internalChannel = null;

            lock (Channels)
            {
                if (!Channels.ContainsKey(channel))
                {
                    return;
                }
                internalChannel = Channels[channel];
            }

            lock (internalChannel.Clients)
                internalChannel.Clients.Remove(ws);
            ws.Channels.Remove(channel);
        }
        public override byte[] PrepareToSend(byte[] data)
        {
            data = InternalChannel.PrepareToSend(data);
            byte[] sequenceBytes = BitConverter.GetBytes(_outgoingSequence);
            var    newData       = new byte[data.Length + sequenceBytes.Length];

            Array.Copy(sequenceBytes, 0, newData, 0, sequenceBytes.Length);
            Array.Copy(data, 0, newData, sequenceBytes.Length, data.Length);
            if (_sendAcks)
            {
                lock (_outboxLock)
                {
                    _outbox[_outgoingSequence] = new OutboxItem()
                    {
                        data = newData, nextSendTime = DateTime.UtcNow.Ticks + ACK_TIMEOUT_DURATION_IN_TICKS
                    };
                }
            }
            _outgoingSequence++;
            return(newData);
        }
Example #7
0
        /// Websocket methods
        public static async Task AddClientToChannelAsync(ConnectedClient ws, string channel)
        {
            if (ws.Channels.Contains(channel))
            {
                return;
            }

            IdentityHandler.InternalIdentity identity = null;
            if (channel.StartsWith("https://") || channel.StartsWith("http://"))
            {
                // Check if this client is allowed to join this channel
                identity = await IdentityHandler.GetIdentityAsync(ws.ClientId, channel);

                if (identity == null)
                {
                    return;
                }
            }

            InternalChannel internalChannel = null;

            lock (Channels)
            {
                if (!Channels.ContainsKey(channel))
                {
                    Channels.Add(channel, new InternalChannel()
                    {
                        Channel     = channel,
                        LastMessage = DateTime.UtcNow,
                        Messages    = new ChannelMessageData[MaxMessageBuffer],
                        CurIndex    = 0,
                        Clients     = new List <ConnectedClient>()
                    });
                }
                internalChannel = Channels[channel];
            }
            lock (internalChannel.Clients)
                internalChannel.Clients.Add(ws);
            ws.Channels.Add(channel);
        }
Example #8
0
        public override byte[] PrepareToSend(byte[] data)
        {
            data = InternalChannel.PrepareToSend(data);
            byte[] sequenceBytes = BitConverter.GetBytes(_outgoingSequence);
            var    newData       = new byte[data.Length + sequenceBytes.Length];

            Array.Copy(sequenceBytes, 0, newData, 0, sequenceBytes.Length);
            Array.Copy(data, 0, newData, sequenceBytes.Length, data.Length);
            if (_sendAcks)
            {
                lock (_outboxLock)
                {
                    _outbox[_outgoingSequence] = new OutboxItem()
                    {
                        data = newData, lastSendTime = DateTime.UtcNow.Ticks
                    };
                }
            }
            _outgoingSequence++;
            //UnityEngine.Debug.LogError("Prepare: " + GetType().ToString() + ": " + DeBox.Teleport.Debugging.TeleportDebugUtils.DebugString(newData));
            return(newData);
        }
Example #9
0
        private void ProcessOutbox()
        {
            if (_outbox.Count == 0 || !_sendAcks)
            {
                return;
            }
            ushort     seqId;
            OutboxItem outboxItem;

            lock (_outboxLock)
            {
                foreach (var p in _outbox)
                {
                    seqId      = p.Key;
                    outboxItem = p.Value;
                    if (outboxItem.lastSendTime < DateTime.UtcNow.Ticks - 10000000)
                    {
                        outboxItem.lastSendTime = DateTime.UtcNow.Ticks;
                        InternalChannel.Send(outboxItem.data);
                    }
                }
            }
        }
        private void ProcessOutbox()
        {
            if (_outbox.Count == 0 || !_sendAcks)
            {
                return;
            }
            ushort     seqId;
            OutboxItem outboxItem;

            lock (_outboxLock)
            {
                foreach (var p in _outbox)
                {
                    seqId      = p.Key;
                    outboxItem = p.Value;
                    if (outboxItem.nextSendTime < DateTime.UtcNow.Ticks)
                    {
                        outboxItem.nextSendTime = DateTime.UtcNow.Ticks + ACK_TIMEOUT_DURATION_IN_TICKS * (1 + (_outbox.Count / ACK_TIMEOUT_INCREMENT_PER_MESSAGE_COUNT));
                        InternalChannel.Send(outboxItem.data);
                    }
                }
            }
        }
Example #11
0
 public override void Send(byte[] data)
 {
     InternalChannel.Send(data);
     ProcessOutbox();
 }
Example #12
0
        public static async Task <ChannelData> GetMessagesForChannelSinceIndexAsync(string clientId, string channel, long index)
        {
            // If Channel starts with https:// , use the clientId to request the identity from the url
            IdentityHandler.InternalIdentity identity = null;
            if (channel.StartsWith("https://") || channel.StartsWith("http://"))
            {
                identity = await IdentityHandler.GetIdentityAsync(clientId, channel);

                if (identity == null)
                {
                    return(null);
                }
            }

            InternalChannel internalChannel = null;

            lock (Channels)
            {
                if (!Channels.ContainsKey(channel))
                {
                    return(null);
                }
                internalChannel = Channels[channel];
            }

            var container = new ChannelData()
            {
                Channel = channel
            };

            if (identity != null && !identity.Data.allowChannelReceive) // Check if we are allowed to receive messages
            {
                container.Messages = new List <ChannelMessageData>();
                return(container);
            }

            if (index == -1) // On the first request from the client (index == -1), we will only give back at what position we are.
            {
                container.Index    = internalChannel.CurIndex;
                container.Messages = new List <ChannelMessageData>();
                return(container);
            }

            // Find out count to pre-allocate the memory space before going into our locked section
            var count = internalChannel.CurIndex - index;

            if (count > MaxMessageBuffer)
            {
                count = MaxMessageBuffer;
            }
            if (count <= 0)
            {
                container.Messages = new List <ChannelMessageData>();
                container.Index    = internalChannel.CurIndex;
                return(container);
            }
            container.Messages = new List <ChannelMessageData>((int)count);

            lock (internalChannel.Messages)
            {
                // In case the CurIndex is changed before we got the lock
                container.Index = internalChannel.CurIndex;
                count           = internalChannel.CurIndex - index;
                if (count > MaxMessageBuffer || count < 0)
                {
                    count = MaxMessageBuffer;
                }

                for (var i = internalChannel.CurIndex - count; i < internalChannel.CurIndex; i++)
                {
                    var arrayIndex = i % MaxMessageBuffer;
                    var messageObj = internalChannel.Messages[(int)arrayIndex];
                    if (messageObj.ClientId == clientId)
                    {
                        continue;
                    }
                    container.Messages.Add(messageObj);
                }
            }
            return(container);
        }
Example #13
0
        public static async Task SendMessageAsync(string clientId, string channel, string data, ConnectedClient filterClient = null)
        {
            if (data.Length > 1024 * 4)
            {
                return;
            }

            // If Channel starts with https:// , use the clientId to request the identity from the url
            IdentityHandler.InternalIdentity identity = null;
            if (channel.StartsWith("https://") || channel.StartsWith("http://"))
            {
                identity = await IdentityHandler.GetIdentityAsync(clientId, channel);

                if (identity == null || !identity.Data.allowChannelSend)
                {
                    return;
                }
            }

            // Add to channel message hub
            InternalChannel internalChannel = null;

            lock (Channels)
            {
                if (!Channels.ContainsKey(channel))
                {
                    Channels.Add(channel, new InternalChannel()
                    {
                        Channel     = channel,
                        LastMessage = DateTime.UtcNow,
                        Messages    = new ChannelMessageData[MaxMessageBuffer],
                        CurIndex    = 0,
                        Clients     = new List <ConnectedClient>()
                    });
                }
                internalChannel = Channels[channel];
            }
            var message = new ChannelMessageData()
            {
                Data     = data,
                Identity = identity,
                ClientId = clientId
            };

            lock (internalChannel.Messages)
            {
                var arrayIndex = internalChannel.CurIndex % MaxMessageBuffer;
                internalChannel.Messages[arrayIndex] = message;
                internalChannel.CurIndex++;
                internalChannel.LastMessage = DateTime.UtcNow;
            }

            // Broadcast to all websocket connected clients
            List <ConnectedClient> clients = null;

            lock (internalChannel.Clients)
                clients = internalChannel.Clients.Where(a => (filterClient != null && a != filterClient) || (filterClient == null && a.ClientId != clientId)).ToList();

            if (clients.Count > 0)
            {
                var json = System.Text.Json.JsonSerializer.Serialize(new CommandMessageData()
                {
                    Channel  = channel,
                    Identity = identity?.Data?.publicIdentifier,
                    Data     = data
                });

                var dataBytes = System.Text.ASCIIEncoding.UTF8.GetBytes("MSG|" + json.Length + "|" + json); // MSG = 'Channel Message' Command Type
                foreach (var client in clients)
                {
                    _ = client.SendDataAsync(dataBytes);
                }
            }
        }