public void InternalSend(PiranhaMessage message)
        {
            if (message.GetEncodingLength() == 0)
            {
                message.Encode();
            }

            int encodingLength = message.GetEncodingLength();
            int encryptedLength;

            byte[] encodingBytes = message.GetMessageBytes();
            byte[] encryptedBytes;

            if (this.m_sendEncrypter != null)
            {
                if (!this.m_encryptionScrambled && message.GetMessageType() == LoginOkMessage.MESSAGE_TYPE)
                {
                    byte[] nonce = Messaging.CreateNonce();

                    ExtendedSetEncryptionMessage extendedSetEncryptionMessage = new ExtendedSetEncryptionMessage();

                    extendedSetEncryptionMessage.SetNonce(nonce);
                    extendedSetEncryptionMessage.SetNonceMethod(Messaging.NONCE_METHOD);

                    this.InternalSend(extendedSetEncryptionMessage);
                    this.SetEncryption(extendedSetEncryptionMessage);
                }

                encryptedLength = encodingLength + this.m_sendEncrypter.GetOverheadEncryption();
                encryptedBytes  = new byte[encryptedLength];

                this.EncryptUsingEncrypter(encodingBytes, encryptedBytes, encodingLength);
            }
            else if (this.m_pepperState != PepperState.DISABLED)
            {
                if (this.m_pepperState == PepperState.AUTHENTIFICATION)
                {
                    if (message.GetMessageType() == ServerHelloMessage.MESSAGE_TYPE)
                    {
                        this.m_pepperState = PepperState.AUTHENTIFICATION_SERVER;
                    }

                    encryptedLength = encodingLength;
                    encryptedBytes  = encodingBytes;
                }
                else if (this.m_pepperState == PepperState.LOGIN)
                {
                    throw new NotImplementedException();
                }
                else
                {
                    encryptedLength = encodingLength;
                    encryptedBytes  = encodingBytes;
                }
            }
            else
            {
                encryptedBytes  = encodingBytes;
                encryptedLength = encodingLength;
            }

            byte[] stream = new byte[encryptedLength + Messaging.HEADER_SIZE];

            Messaging.WriteHeader(message, stream, encryptedLength);
            Buffer.BlockCopy(encryptedBytes, 0, stream, Messaging.HEADER_SIZE, encryptedLength);

            this.m_clientConnection.Send(stream, encryptedLength + Messaging.HEADER_SIZE);
        }
        public int OnReceive(byte[] buffer, int length)
        {
            if (length >= Messaging.HEADER_SIZE)
            {
                Messaging.ReadHeader(buffer, out int messageType, out int messageLength, out int messageVersion);

                if (length - Messaging.HEADER_SIZE >= messageLength)
                {
                    byte[] encryptedBytes = new byte[messageLength];
                    byte[] encodingBytes;

                    Buffer.BlockCopy(buffer, Messaging.HEADER_SIZE, encryptedBytes, 0, messageLength);

                    int encodingLength;

                    if (this.m_receiveEncrypter != null)
                    {
                        encodingLength = messageLength - this.m_receiveEncrypter.GetOverheadEncryption();
                        encodingBytes  = new byte[encodingLength];

                        this.DecryptUsingEncrypter(encryptedBytes, encodingBytes, messageLength);
                    }
                    else
                    {
                        if (this.m_pepperState == PepperState.DEFAULT)
                        {
                            if (messageType == ClientHelloMessage.MESSAGE_TYPE)
                            {
                                this.m_pepperState = PepperState.AUTHENTIFICATION;

                                encodingLength = messageLength;
                                encodingBytes  = encryptedBytes;
                            }
                            else if (messageType == LoginMessage.MESSAGE_TYPE)
                            {
                                this.m_pepperState = PepperState.DISABLED;
                                this.InitRC4Encryption(this.GetDefaultNonce());

                                encodingLength = messageLength - this.m_receiveEncrypter.GetOverheadEncryption();
                                encodingBytes  = new byte[encodingLength];

                                this.DecryptUsingEncrypter(encryptedBytes, encodingBytes, messageLength);
                            }
                            else
                            {
                                return(messageLength + Messaging.HEADER_SIZE);
                            }
                        }
                        else if (this.m_pepperState == PepperState.AUTHENTIFICATION_SERVER)
                        {
                            if (messageType != LoginMessage.MESSAGE_TYPE)
                            {
                                return(messageLength + Messaging.HEADER_SIZE);
                            }
                            throw new NotImplementedException();
                        }
                        else
                        {
                            return(messageLength + Messaging.HEADER_SIZE);
                        }
                    }

                    PiranhaMessage piranhaMessage = this.m_messageFactory.CreateMessageByType(messageType);

                    if (piranhaMessage != null)
                    {
                        piranhaMessage.GetByteStream().SetByteArray(encodingBytes, encodingLength);
                        piranhaMessage.SetMessageVersion(messageVersion);

                        try
                        {
                            piranhaMessage.Decode();

                            if (!piranhaMessage.IsServerToClientMessage())
                            {
                                MessageHandler.EnqueueReceive(piranhaMessage, this.m_clientConnection);
                            }
                        }
                        catch (Exception exception)
                        {
                            Logging.Error(string.Format("Messaging::onReceive: error while the decoding of message type {0}, trace: {1}", messageType, exception));
                        }
                    }
                    else
                    {
                        Logging.Warning(string.Format("Messaging::onReceive: ignoring message of unknown type {0}", messageType));
                    }

                    return(messageLength + Messaging.HEADER_SIZE);
                }
                else
                {
                    int httpHeader = buffer[0] << 16 | buffer[1] << 8 | buffer[2];

                    if (httpHeader == 0x474554) // httpHeader == GET
                    {
                        return(-1);
                    }
                }
            }

            return(0);
        }