/// <summary>
 /// Register and subscribe to packet receive event
 /// </summary>
 /// <param name="onReceive">event that will be called when packet deserialized with ReadPacket method</param>
 /// <param name="packetConstructor">Method that constructs packet intead of slow Activator.CreateInstance</param>
 /// <exception cref="InvalidTypeException"><typeparamref name="T"/>'s fields are not supported, or it has no fields</exception>
 public void Subscribe <T>(Action <T> onReceive, Func <T> packetConstructor) where T : class, new()
 {
     //_netSerializer.Register<T>();
     _callbacks[GetHash(typeof(T))] = (reader, userData) =>
     {
         //var reference = packetConstructor();
         long bytesRead;
         var  reference = _netSerializer.Deserialize <T>(reader.RawData, reader.UserDataOffset + 8, reader.RawDataSize, out bytesRead);
         pos += bytesRead;
         onReceive(reference);
     };
 }
Ejemplo n.º 2
0
        protected override void Test(FTestMessage message, Action <FTestMessage> customAssert = null)
        {
            var serialized   = ProtoSerializer.Serialize(message);
            var deserialized = ProtoSerializer.Deserialize <FTestMessage>(serialized);

            AssertDeserialized(message, deserialized, customAssert);
        }
Ejemplo n.º 3
0
 protected override void Test(FTestMessage message, Action <FTestMessage> customAssert = null)
 {
     using (var pool = ProtoSerializer.SerializePooled(message))
     {
         var buf          = pool.Item;
         var deserialized = ProtoSerializer.Deserialize <FTestMessage>(buf.Buffer, buf.Offset, buf.Count);
         AssertDeserialized(message, deserialized, customAssert);
     }
 }
Ejemplo n.º 4
0
 protected override void Test(FTestMessage message, Action <FTestMessage> customAssert = null)
 {
     using (var ms = new MemoryStream())
     {
         ProtoSerializer.Serialize(ms, message);
         ms.Position = 0;
         var deserialized = (FTestMessage)ProtoSerializer.Deserialize(typeof(FTestMessage), ms);
         AssertDeserialized(message, deserialized, customAssert);
     }
 }
Ejemplo n.º 5
0
 private void LoadSettings()
 {
     if (!File.Exists(PathManager.SettingsFileName))
     {
         Settings = new Settings();
     }
     else
     {
         try
         {
             var data = File.ReadAllBytes(PathManager.SettingsFileName);
             Settings = ProtoSerializer.Deserialize <Settings>(data) ?? new Settings();
         }
         catch (Exception ex)
         {
             AppLogger.Error(ex, "Failed load settings.");
         }
     }
 }
Ejemplo n.º 6
0
        private void SendDataAsync()
        {
            uint sequenceId = 0;

            while (true)
            {
                if (sequenceId == 0)
                {
                    sequenceId = this.session.GetResendSequenceAsync();
                }

                if (sequenceId == 0)
                {
                    try
                    {
                        this.WaitForSendWindowAsync(this.session.Context);
                    }
                    catch (Exception e)
                    {
                        if (e == Constants.MaxWaitError)
                        {
                            continue;
                        }

                        throw e;
                    }

                    var nextSendSequenceId = this.session.GetSendSequenceAsync();

                    sequenceId = nextSendSequenceId.Value;
                }

                var data = this.session.GetDataToSend(sequenceId);
                if (data == null)
                {
                    this.sequencesSentTimes.Remove(sequenceId);
                    this.sequencesResentTimes.Remove(sequenceId);

                    sequenceId = 0;

                    continue;
                }

                try
                {
                    var packet = ProtoSerializer.Deserialize <Packet>(data);
                    if (packet.SequenceId != sequenceId)
                    {
                        throw new Exception("sequence missmatch");
                    }

                    Console.WriteLine($"Sending session message. Packet Id: {sequenceId}, Data Length: {packet.Data.Length}, Data: {string.Join(", ", packet.Data.Take(10))}");
                    this.session.SendDataAsync(this.LocalClientId, this.RemoteClientId, data);
                }
                catch (Exception e)
                {
                    if (this.session.IsClosed)
                    {
                        throw new SessionClosedException();
                    }

                    var cts          = new CancellationTokenSource();
                    var channelTasks = new List <Task <Channel <uint?> > >
                    {
                        this.session.ResendChannel.Push(sequenceId, cts.Token),
                        this.session.Context.DoneChannel.Shift(cts.Token)
                    };

                    var channel = channelTasks.FirstAsync(cts);
                    if (channel == this.session.ResendChannel)
                    {
                        sequenceId = 0;
                        break;
                    }
                    else if (channel == this.session.Context.DoneChannel)
                    {
                        throw this.session.Context.Error;
                    }

                    Thread.Sleep(1000);
                    continue;
                }

                if (this.sequencesSentTimes.ContainsKey(sequenceId) == false)
                {
                    this.sequencesSentTimes.Add(sequenceId, DateTime.Now);
                }

                this.sequencesResentTimes.Remove(sequenceId);

                sequenceId = 0;
            }
        }
Ejemplo n.º 7
0
        private async Task <bool> HandleInboundMessageAsync(byte[] data)
        {
            var inboundMessage = ProtoSerializer.Deserialize <InboundMessage>(data);

            if (inboundMessage.PreviousSignature?.Length > 0)
            {
                var previousSignatureHex = inboundMessage.PreviousSignature.ToHexString();

                var receipt      = MessageFactory.MakeReceipt(this.key, previousSignatureHex);
                var receiptBytes = receipt.ToBytes();

                this.SendThroughSocket(receiptBytes);
            }

            var messagePayload = ProtoSerializer.Deserialize <MessagePayload>(inboundMessage.Payload);

            var payloadBytes = this.GetPayload(messagePayload, inboundMessage.Source);

            var payload = ProtoSerializer.Deserialize <Payload>(payloadBytes);

            string textMessage = null;

            switch (payload.Type)
            {
            case PayloadType.Binary:
                break;

            case PayloadType.Text:
                var textData = ProtoSerializer.Deserialize <TextDataPayload>(payload.Data);
                textMessage = textData.Text;
                break;

            case PayloadType.Ack:
                this.textResponseManager.ProcessResponse(payload.ReplyToId, null, payload.Type);
                this.binaryResponseManager.ProcessResponse(payload.ReplyToId, null, payload.Type);
                return(true);

            case PayloadType.Session:
                break;

            default:
                break;
            }

            if (payload.ReplyToId?.Length > 0)
            {
                if (textMessage == null)
                {
                    this.binaryResponseManager.ProcessResponse(payload.ReplyToId, payload.Data, payload.Type);
                }
                else
                {
                    this.textResponseManager.ProcessResponse(payload.ReplyToId, textMessage, payload.Type);
                }

                return(true);
            }

            var responses = Enumerable.Empty <object>();

            switch (payload.Type)
            {
            case PayloadType.Binary:
            case PayloadType.Session:
            case PayloadType.Text:

                var request = new MessageHandlerRequest
                {
                    Source      = inboundMessage.Source,
                    Payload     = payload.Data,
                    PayloadType = payload.Type,
                    IsEncrypted = messagePayload.IsEncrypted,
                    MessageId   = payload.MessageId,
                    NoReply     = payload.NoReply,
                    TextMessage = textMessage
                };

                var tasks = this.messageHandlers.Select(async func =>
                {
                    try
                    {
                        return(await func(request));
                    }
                    catch (Exception)
                    {
                        return(null);
                    }
                });

                responses = await Task.WhenAll(tasks);

                break;

            case PayloadType.Ack:
                break;
            }

            if (payload.NoReply == false)
            {
                var responded = false;
                foreach (var response in responses)
                {
                    if (response is bool res)
                    {
                        if (res == false)
                        {
                            return(true);
                        }
                    }
                    else if (response != null)
                    {
                        if (response is byte[] bytes)
                        {
                            this.SendDataAsync <byte[]>(inboundMessage.Source, bytes, new SendOptions
                            {
                                IsEncrypted = messagePayload.IsEncrypted,
                                ReplyToId   = payload.MessageId.ToHexString()
                            });

                            responded = true;
                            break;
                        }
                        else if (response is string text)
                        {
                            this.SendTextAsync <string>(inboundMessage.Source, text, new SendOptions
                            {
                                IsEncrypted = messagePayload.IsEncrypted,
                                ReplyToId   = payload.MessageId.ToHexString()
                            });

                            responded = true;
                            break;
                        }
                    }
                }

                if (responded == false)
                {
                    this.SendAck(inboundMessage.Source, payload.MessageId, messagePayload.IsEncrypted);
                }
            }

            return(true);
        }
Ejemplo n.º 8
0
 private void addTestModel(byte[] model) =>
 data.Add(ProtoSerializer.Deserialize <TestModel>(model));
Ejemplo n.º 9
0
        public async Task ReceiveWithClientAsync(string localClientId, string remoteClientId, byte[] buffer)
        {
            if (this.IsClosed)
            {
                throw new SessionClosedException();
            }

            var packet = ProtoSerializer.Deserialize <Packet>(buffer);

            if (packet.Data != null)
            {
                Console.WriteLine($"Receiving session message. Packet Id: {packet.SequenceId}, Data Lengtht: {packet.Data?.Length}, Data: {(packet.Data == null ? string.Empty : string.Join(", ", packet.Data.Take(10)))}");
            }

            if (packet.IsClose)
            {
                this.HandleClosePacket();
                return;
            }

            var established = this.isEstablished;

            if (established == false && packet.IsHandshake)
            {
                this.HandleHandshakePacketAsync(packet);
                return;
            }

            if (established && (packet.AckStartSeqs?.Length > 0 || packet.AckSeqCounts?.Length > 0))
            {
                if (packet.AckSeqCounts?.Length > 0 &&
                    packet.AckStartSeqs?.Length > 0 &&
                    packet.AckStartSeqs?.Length != packet.AckSeqCounts?.Length)
                {
                    throw new InvalidPacketException("AckStartSeq and AckSeqCount should have the same length if both are non-empty");
                }

                int count;
                if (packet.AckStartSeqs.Length > 0)
                {
                    count = packet.AckStartSeqs.Length;
                }
                else
                {
                    count = packet.AckSeqCounts.Length;
                }

                uint ackStartSequenceId;
                uint ackEndSequenceId;

                for (int i = 0; i < count; i++)
                {
                    if (packet.AckStartSeqs.Length > 0)
                    {
                        ackStartSequenceId = packet.AckStartSeqs[i];
                    }
                    else
                    {
                        ackStartSequenceId = Constants.MinSequenceId;
                    }

                    if (packet.AckSeqCounts?.Length > 0)
                    {
                        var step = (int)packet.AckSeqCounts[i];
                        ackEndSequenceId = Session.NextSequenceId(ackStartSequenceId, step);
                    }
                    else
                    {
                        ackEndSequenceId = Session.NextSequenceId(ackStartSequenceId);
                    }

                    var nextSequenceAvailable = Session.IsSequenceInbetween(
                        this.sendWindowStartSequenceId,
                        this.sendWindowEndSequenceId,
                        Session.NextSequenceId(ackEndSequenceId, -Session.DefaultStepSize));

                    if (nextSequenceAvailable)
                    {
                        var ackIsInBounds = Session.IsSequenceInbetween(
                            this.sendWindowStartSequenceId,
                            this.sendWindowEndSequenceId,
                            ackStartSequenceId);

                        if (ackIsInBounds == false)
                        {
                            ackStartSequenceId = this.sendWindowStartSequenceId;
                        }

                        for (
                            var currentSequenceId = ackStartSequenceId;
                            Session.IsSequenceInbetween(ackStartSequenceId, ackEndSequenceId, currentSequenceId);
                            currentSequenceId = Session.NextSequenceId(currentSequenceId))
                        {
                            foreach (var connection in this.connections)
                            {
                                var isSentByMe = connection.Key == Connection.GetKey(localClientId, remoteClientId);

                                connection.Value.ReceiveAck(currentSequenceId, isSentByMe);
                            }

                            this.sendWindowData.Remove(currentSequenceId);
                        }

                        if (ackStartSequenceId == this.sendWindowStartSequenceId)
                        {
                            while (true)
                            {
                                this.sendWindowStartSequenceId = Session.NextSequenceId(this.sendWindowStartSequenceId);

                                if (this.sendWindowData.ContainsKey(this.sendWindowStartSequenceId))
                                {
                                    break;
                                }

                                if (this.sendWindowStartSequenceId == this.sendWindowEndSequenceId)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if (established && packet.BytesRead > this.remoteBytesRead)
            {
                this.remoteBytesRead = packet.BytesRead;

                var cts          = new CancellationTokenSource();
                var channelTasks = new List <Task <Channel <uint?> > >
                {
                    this.sendWindowUpdateChannel.Push(null, cts.Token),
                    Constants.ClosedChannel.Shift(cts.Token)
                };

                await channelTasks.FirstAsync(cts);
            }

            if (established && packet.SequenceId > 0)
            {
                if (packet.Data.Length > this.recieveMtu)
                {
                    throw new DataSizeTooLargeException();
                }

                if (Session.CompareSequenceIds(packet.SequenceId, this.receiveWindowStartSeq) >= 0)
                {
                    if (this.receiveWindowData.ContainsKey(packet.SequenceId) == false)
                    {
                        if (this.receiveWindowUsed + packet.Data.Length > this.receiveWindowSize)
                        {
                            throw new RecieveWindowFullException();
                        }

                        this.receiveWindowData.TryAdd(packet.SequenceId, packet.Data);
                        this.receiveWindowUsed += packet.Data.Length;

                        if (packet.SequenceId == this.receiveWindowStartSeq)
                        {
                            var cts2          = new CancellationTokenSource();
                            var channelTasks2 = new List <Task <Channel <uint?> > >
                            {
                                this.recieveDataUpdateChannel.Push(null, cts2.Token),
                                Constants.ClosedChannel.Shift(cts2.Token)
                            };

                            await channelTasks2.FirstAsync(cts2);
                        }
                    }
                }

                var connectionKey = Connection.GetKey(localClientId, remoteClientId);
                if (this.connections.ContainsKey(connectionKey))
                {
                    var conn = this.connections[connectionKey];
                    conn.SendAck(packet.SequenceId);
                }
            }
        }
Ejemplo n.º 10
0
 public static T FromBytes <T>(this byte[] data) where T : class, ISerializable
 {
     return(ProtoSerializer.Deserialize <T>(data));
 }