Esempio n. 1
0
        //public void SendMessage(RawMessage message)
        //{
        //    SendMessageAsync(message);
        //}

        public virtual async Task SendMessageAsync(TcpRawMessage message)
        {
            if (!Connected)
            {
                message.Dispose();
                throw new InvalidOperationException($"Connection is not established");
            }

            if (Parent.Configuration.ConnectionSimulation != null)
            {
                int delay = Parent.Configuration.ConnectionSimulation.GetHalfDelay();
                if (delay > 0)
                {
                    await Task.Delay(delay).ConfigureAwait(false);
                }
            }

            Task newSendTask = null;

            lock (sendMutex)
            {
                sendTask = sendTask.ContinueWith(
                    (task, msg) =>
                {
                    return(SendMessageInternalAsync(msg as TcpRawMessage));
                }, message)
                           .Unwrap();

                newSendTask = sendTask;
            }

            await newSendTask.ConfigureAwait(false);
        }
Esempio n. 2
0
        public virtual void Stash()
        {
            if (Disposed)
            {
                throw new ObjectDisposedException(nameof(TcpConnection));
            }
            if (Stashed)
            {
                return;
            }

            Close();
            DestroySocket();

            this.awaitingMessageHeader.Reset();
            this.Statistics.Reset();
            this.lastKeepAliveSent              = new DateTime(0);
            this.awaitingNextMessageWrote       = 0;
            this.awaitingNextMessageHeaderValid = false;
            this.LastKeepAliveRequestReceived   = null;

            if (this.awaitingNextMessage != null)
            {
                this.awaitingNextMessage.Dispose();
                this.awaitingNextMessage = null;
            }

            while (this.latencySimulationRecvQueue.TryDequeue(out DelayedMessage removed))
            {
                removed.message.Dispose();
            }

            stashed = true;
            logger.Debug($"Connection #{Id} stashed!");
        }
Esempio n. 3
0
        /// <summary>
        /// Returns the memory used by this connection
        /// </summary>
        /// <param name="disposing">Whether we're disposing (true), or being called by the finalizer (false)</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposed)
            {
                return;
            }
            disposed = true;

            Close();
            DestroySocket();

            if (this.awaitingNextMessage != null)
            {
                this.awaitingNextMessage.Dispose();
                this.awaitingNextMessage = null;
            }

            if (sendSemaphore != null)
            {
                sendSemaphore.Dispose();
                sendSemaphore = null;
            }

            logger.Debug($"Connection #{Id} disposed!");
        }
Esempio n. 4
0
        public bool SendReliable(ICustomMessage message)
        {
            if (!this.Connected)
            {
                return(false);
            }

            TcpRawMessage rawMessage = Parent.CreateMessage();

            using (WardenStreamWriter sw = new WardenStreamWriter(rawMessage.BaseStream, true))
            {
                message.WriteTo(new WriteFormatterInfo(sw, configuration.Serializer));
            }

            if (rawMessage.Length >= configuration.CompressionThreshold)
            {
                logger.Trace($"Message {message} size exceeds compression threshold {configuration.CompressionThreshold}, compressing it");
                using (rawMessage)
                {
                    var compressedMessage = rawMessage.Compress(CompressionLevel.Optimal);
                    logger.Trace($"Compressing {rawMessage} to {compressedMessage}");
                    compressedMessage.Position = 0;
                    SendRawMessage(compressedMessage);
                }
            }
            else
            {
                SendRawMessage(rawMessage);
            }

            return(true);
        }
 private protected override void SendRawMessage(TcpRawMessage message)
 {
     using (message)
     {
         message.Position = 0;
         TcpRawMessage encryptedMessage = message.Encrypt(cipher);
         logger.Trace($"Encrypting {message} to {encryptedMessage}");
         base.SendRawMessage(encryptedMessage);
     }
 }
Esempio n. 6
0
        protected internal virtual void PollEventsInternal()
        {
            if (Parent.Configuration.KeepAliveEnabled)
            {
                TimeSpan timeSinceLastKeepAlive = DateTime.UtcNow - this.lastKeepAliveSent;

                if (keepAliveResponseGot)
                {
                    if (timeSinceLastKeepAlive.TotalMilliseconds > Parent.Configuration.KeepAliveInterval)
                    {
                        keepAliveResponseGot   = false;
                        this.lastKeepAliveSent = DateTime.UtcNow;
                        _ = SendMessageAsync(TcpRawMessage.GetEmpty(Parent.Configuration.MemoryStreamPool, MessageHeaderFlags.KeepAliveRequest));
                    }
                }
                else
                {
                    if (timeSinceLastKeepAlive.TotalMilliseconds > TcpConnectionStatistics.UNSTABLE_CONNECTION_TIMEOUT)
                    {
                        Statistics.SetUnstable();
                    }

                    if (Parent.Configuration.KeepAliveTimeout > Timeout.Infinite && timeSinceLastKeepAlive.TotalMilliseconds > Parent.Configuration.KeepAliveTimeout)
                    {
                        logger.Debug($"Connection #{Id} closing, KeepAliveTimeout exceeded");
                        Close();
                    }
                }
            }

            Statistics.PollEvents();

            while (latencySimulationRecvQueue.Count > 0 && Connected)
            {
                if (latencySimulationRecvQueue.TryPeek(out DelayedMessage msg))
                {
                    if (DateTime.UtcNow > msg.releaseTimestamp)
                    {
                        latencySimulationRecvQueue.TryDequeue(out DelayedMessage _msg);
                        OnMessageReceivedInternal(msg.message);
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }
            }
        }
Esempio n. 7
0
 public MessageEventArgs(TcpConnection connection, TcpRawMessage message)
 {
     if (connection == null)
     {
         throw new ArgumentNullException(nameof(connection));
     }
     if (message == null)
     {
         throw new ArgumentNullException(nameof(message));
     }
     this.Connection = connection;
     this.Message    = message;
 }
Esempio n. 8
0
        void OnMessageReceivedInternalWithSimulation(TcpRawMessage message)
        {
            if (Parent.Configuration.ConnectionSimulation != null)
            {
                int delay = Parent.Configuration.ConnectionSimulation.GetHalfDelay();
                latencySimulationRecvQueue.Enqueue(new DelayedMessage()
                {
                    message          = message,
                    releaseTimestamp = DateTime.UtcNow.AddMilliseconds(delay)
                });
                return;
            }

            OnMessageReceivedInternal(message);
        }
Esempio n. 9
0
        void OnMessageReceivedInternal(TcpRawMessage message)
        {
            if (message.Flags.HasFlag(MessageHeaderFlags.KeepAliveRequest) ||
                message.Flags.HasFlag(MessageHeaderFlags.KeepAliveResponse))
            {
                logger.Trace($"Connection #{Id} recv message {message}");
            }
            else
            {
                logger.Debug($"Connection #{Id} recv message {message}");
            }

            if (message.Flags.HasFlag(MessageHeaderFlags.KeepAliveRequest))
            {
                LastKeepAliveRequestReceived = DateTime.UtcNow;
                _ = SendMessageAsync(TcpRawMessage.GetEmpty(Parent.Configuration.MemoryStreamPool, MessageHeaderFlags.KeepAliveResponse));
                message.Dispose();
                return;
            }

            if (message.Flags.HasFlag(MessageHeaderFlags.KeepAliveResponse))
            {
                Statistics.UpdateLatency((float)(DateTime.UtcNow - this.lastKeepAliveSent).TotalMilliseconds);
                keepAliveResponseGot = true;
                message.Dispose();
                return;
            }

            Parent.Configuration.SynchronizeSafe(() =>
            {
                try
                {
                    OnMessageReceived(new MessageEventArgs(this, message));
                }
                catch (Exception ex)
                {
                    logger.Error($"Unhandled exception in #{Id} -> {this.GetType().Name}.OnMessageReceived: {ex}");
                }
            }, logger);
        }
Esempio n. 10
0
        async Task SendMessageInternalAsync(TcpRawMessage message)
        {
            try
            {
                var socket = this.socket;
                if (!Connected)
                {
                    return; // throw new OperationCanceledException("Send operation cancelled. Connection not established");
                }
                await sendSemaphore.WaitAsync().ConfigureAwait(false);

                if (message.Flags.HasFlag(MessageHeaderFlags.KeepAliveRequest) ||
                    message.Flags.HasFlag(MessageHeaderFlags.KeepAliveResponse))
                {
                    logger.Trace($"Connection #{Id} sending {message}");
                }
                else
                {
                    logger.Debug($"Connection #{Id} sending {message}");
                }

                TcpRawMessageHeader header = new TcpRawMessageHeader(message);

                var headerBytes = header.Build();
                Buffer.BlockCopy(headerBytes.Array, headerBytes.Offset, sendBuffer, 0, headerBytes.Count);
                int  bufferPosition = headerBytes.Count;
                int  totalBytesSent = 0;
                bool messageEof     = false;

                message.Position = 0;

                do
                {
                    int bufferFreeSpace  = sendBuffer.Length - bufferPosition;
                    int messageLeftBytes = (int)(message.BaseStream.Length - message.BaseStream.Position);
                    int toCopy           = bufferFreeSpace;
                    if (messageLeftBytes <= toCopy)
                    {
                        toCopy     = messageLeftBytes;
                        messageEof = true;
                    }
                    message.BaseStream.Read(sendBuffer, bufferPosition, toCopy);
                    bufferPosition += toCopy;

                    int bufferSendPosition = 0;

                    while (bufferSendPosition < bufferPosition)
                    {
                        int sent = await Task.Factory.FromAsync(socket.BeginSend(sendBuffer, bufferSendPosition, bufferPosition - bufferSendPosition, SocketFlags.None, null, null), socket.EndSend)
                                   .ConfigureAwait(false);

                        logger.Trace($"Connection #{Id} sent {sent} bytes");
                        bufferSendPosition += sent;
                        totalBytesSent     += sent;
                    }

                    bufferPosition = 0;
                } while (!messageEof);

                Statistics.PacketOut();
                Statistics.BytesOut(totalBytesSent);
            }
            catch (SocketException)
            {
                Close();
            }
            catch (ObjectDisposedException)
            {
                Close();
            }
            catch (Exception ex)
            {
                logger.Error($"Exception in #{Id} on {message} sending: {ex}");
                Close();
            }
            finally
            {
                sendSemaphore.Release();
                message.Dispose();
            }
        }
Esempio n. 11
0
        internal void ReceiveCallback(IAsyncResult result)
        {
            try
            {
                if (socket == null || !socket.Connected)
                {
                    return;
                }

                int bytesRead = socket.EndReceive(result);

                if (bytesRead == 0)
                {
                    Close();
                    return;
                }

                Statistics.BytesIn(bytesRead);
                logger.Trace($"Connection #{Id} recv data {bytesRead} bytes");

                int recvBufferPos = 0;
                int counter       = 0;

                while (recvBufferPos <= bytesRead)
                {
                    int bytesLeft = bytesRead - recvBufferPos;
                    if (awaitingNextMessage == null)
                    {
                        if (!awaitingNextMessageHeaderValid && bytesLeft > 0)
                        {
                            awaitingNextMessageHeaderValid = awaitingMessageHeader.Write(
                                new ArraySegment <byte>(recvBuffer, recvBufferPos, bytesLeft), out int headerGotRead);
                            recvBufferPos += headerGotRead;
                        }
                        else if (awaitingNextMessageHeaderValid)
                        {
                            awaitingNextMessage      = new TcpRawMessage(Parent.Configuration.MemoryStreamPool, awaitingMessageHeader.MessageSize);
                            awaitingNextMessageWrote = 0;
                        }
                        else if (bytesLeft == 0)
                        {
                            break;
                        }
                    }
                    else
                    {
                        if (awaitingNextMessageWrote < awaitingMessageHeader.MessageSize && bytesLeft > 0)
                        {
                            int toRead = bytesLeft;
                            if (toRead > awaitingMessageHeader.MessageSize - awaitingNextMessageWrote)
                            {
                                toRead = awaitingMessageHeader.MessageSize - awaitingNextMessageWrote;
                            }
                            if (toRead > 0)
                            {
                                awaitingNextMessage.BaseStream.Write(recvBuffer, recvBufferPos, toRead);
                                awaitingNextMessageWrote += toRead;
                                recvBufferPos            += toRead;
                            }
                        }
                        else if (awaitingNextMessageWrote == awaitingMessageHeader.MessageSize)
                        {
                            Statistics.PacketIn();
                            awaitingNextMessage.BaseStream.Position = 0;
                            var message = awaitingNextMessage;
                            awaitingNextMessage = null;
                            message.Flags       = awaitingMessageHeader.Options.Flags;
                            OnMessageReceivedInternalWithSimulation(message);
                            awaitingNextMessageWrote       = 0;
                            awaitingMessageHeader          = new TcpRawMessageHeader();
                            awaitingNextMessageHeaderValid = false;
                        }
                        else if (bytesLeft == 0)
                        {
                            break;
                        }
                    }

                    //Infinite loop protection
                    if (counter++ > recvBuffer.Length / 2 + 100)
                    {
                        logger.Critical($"Infinite loop in {this}");
                        throw new InvalidOperationException("Infinite loop");
                    }
                }

                if (socket != null)
                {
                    StartReceive();
                }
            }
            catch (ObjectDisposedException)
            { }
            catch (SocketException sex)
            {
                if (sex.SocketErrorCode != SocketError.ConnectionReset)
                {
                    logger.Error($"Connection #{Id} broken due to exception: {sex}");
                }
                else
                {
                    logger.Info($"Connection #{Id} reset");
                }
                Close();
            }
            catch (Exception ex)
            {
                logger.Error($"Connection #{Id} broken due to exception: {ex}");
                Close();
            }
        }
Esempio n. 12
0
 private protected virtual void SendRawMessage(TcpRawMessage message)
 {
     _ = this.SendMessageAsync(message);
 }
Esempio n. 13
0
 public void BeforeServerToClient(TcpRawMessage serverMessage)
 {
 }
Esempio n. 14
0
 public void BeforeClientToServer(TcpRawMessage clientMessage)
 {
 }