Beispiel #1
0
 public SocketClient(SocketClientSettings theSocketClientSettings)
 {
     prefixHandler        = new PrefixHandler();
     messageHandler       = new MessageHandler();
     socketClientSettings = theSocketClientSettings;
     token = new DataHoldingUserToken(0, 0);
 }
Beispiel #2
0
        public Int32 HandlePrefix(byte[] buffer, DataHoldingUserToken receiveSendToken,
                                  Int32 remainingBytesToProcess)
        {
            bool incomingTcpMessageIsReady = false;

            // Remember there is a receiveSendToken.receivedPrefixBytesDoneCount
            // variable, which allowed us to handle the prefix even when it
            // requires multiple receive ops. In the same way, we have a
            // receiveSendToken.receivedMessageBytesDoneCount variable, which
            // helps us handle message data, whether it requires one receive
            // operation or many.
            if (remainingBytesToProcess >=
                receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount)
            {
                // If we are inside this if-statement, then we got
                // the end of the message. In other words,
                // the total number of bytes we received for this message matched the
                // message length value that we got from the prefix.

                // Write/append the bytes received to the byte array in the
                // DataHolder object that we are using to store our data.
                receiveSendToken.dataReceived.Write(buffer, receiveSendToken.receiveMessageOffset,
                                                    receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount);

                remainingBytesToProcess -=
                    receiveSendToken.lengthOfCurrentIncomingMessage -
                    receiveSendToken.receivedMessageBytesDoneCount;

                if (remainingBytesToProcess > 0)
                {
                    receiveSendToken.receiveMessageOffset +=
                        receiveSendToken.lengthOfCurrentIncomingMessage -
                        receiveSendToken.receivedMessageBytesDoneCount;
                }
                else
                {
                    receiveSendToken.receiveMessageOffset = receiveSendToken.bufferOffsetReceive;
                }

                receiveSendToken.lengthOfCurrentIncomingMessage = ReadInt32(receiveSendToken.dataReceived.GetBuffer(), 2);
                receiveSendToken.currentMessageCompressed       = (receiveSendToken.lengthOfCurrentIncomingMessage & 1 << 30) != 0;
                if (receiveSendToken.currentMessageCompressed)
                {
                    receiveSendToken.lengthOfCurrentIncomingMessage ^= 1 << 30;
                }

                if (receiveSendToken.lengthOfCurrentIncomingMessage > 65535)
                {
                    receiveSendToken.state = DataHoldingUserToken.State.Error;
                    return(0);
                }

                receiveSendToken.state = DataHoldingUserToken.State.Content;
                receiveSendToken.receivedMessageBytesDoneCount = 0;

                return(remainingBytesToProcess);
            }
            else
            {
                // If we are inside this else-statement, then that means that we
                // need another receive op. We still haven't got the whole message,
                // even though we have examined all the data that was received.
                // Not a problem. In SocketListener.ProcessReceive we will just call
                // StartReceive to do another receive op to receive more data.
                receiveSendToken.dataReceived.Write(buffer, receiveSendToken.receiveMessageOffset, remainingBytesToProcess);

                receiveSendToken.receiveMessageOffset = receiveSendToken.bufferOffsetReceive;

                receiveSendToken.receivedMessageBytesDoneCount += remainingBytesToProcess;

                return(0);
            }
        }
Beispiel #3
0
        /// <summary>
        /// If buffer still has data after call this function, it will return true.
        /// </summary>
        /// <param name="receiveSendEventArgs"></param>
        /// <param name="receiveSendToken"></param>
        /// <param name="remainingBytesToProcess"></param>
        /// <returns></returns>
        private bool ReceiveOneMessage(byte[] buffer, DataHoldingUserToken receiveSendToken,
                                       ref int remainingBytesToProcess)
        {
            // If we have not got all of the prefix then we need to work on it.
            // receivedPrefixBytesDoneCount tells us how many prefix bytes were
            // processed during previous receive ops which contained data for
            // this message. (In normal use, usually there will NOT have been any
            // previous receive ops here. So receivedPrefixBytesDoneCount would be 0.)
            if (receiveSendToken.state == DataHoldingUserToken.State.Prefix)
            {
                remainingBytesToProcess = prefixHandler.HandlePrefix(buffer, receiveSendToken,
                                                                     remainingBytesToProcess);

                if (remainingBytesToProcess == 0)
                {
                    //Jump out of the method, since there is no more data.
                    return(false);
                }
            }

            if (receiveSendToken.state == DataHoldingUserToken.State.Error)
            {
                StartDisconnect();
            }

            // If we have processed the prefix, we can work on the message now.
            // We'll arrive here when we have received enough bytes to read
            // the first byte after the prefix.
            bool incomingTcpMessageIsReady = messageHandler.HandleMessage(buffer, receiveSendToken,
                                                                          ref remainingBytesToProcess);

            if (incomingTcpMessageIsReady)
            {
                // Process the data received, this function should use the data in dataReceived, and Deserialize the data
                // then the dataReceived will be reused  to receive other data.
                //OnMessageRecieved(receiveSendToken.SessionId, receiveSendToken.dataReceived);
                byte[] b;
                int    length = 0;
                if (receiveSendToken.currentMessageCompressed)
                {
                    try
                    {
                        length = LZ4Codec.Decode32(receiveSendToken.dataReceived.GetBuffer(), 0, (int)receiveSendToken.dataReceived.Length, mDecodeBuffer, 0, mDecodeBuffer.Length, false);
                        b      = mDecodeBuffer;
                    }
                    catch (Exception ex)
                    {
                        Logger.Error("Message can not unwrap, this may caused by a hacker's attack." + ex.ToString());
                        b = null;
                    }
                }
                else
                {
                    b      = receiveSendToken.dataReceived.GetBuffer();
                    length = (int)receiveSendToken.dataReceived.Length;
                }

                if (b != null)
                {
                    using (var ms = new MemoryStream(b, 0, length))
                    {
                        var message = SerializerUtility.Deserialize(ms);
                        receiveSendToken.Reset();

                        if (message.Type == (int)MessageType.Ping)
                        {
                            latency = DateTime.Now - DateTime.FromBinary((long)message.ClientId);
                        }
                        else
                        {
                            if (MessageReceived != null)
                            {
                                MessageReceived(message);
                            }
                        }
                    }
                }

                // continue to process another message which is not completed.
                if (remainingBytesToProcess > 0)
                {
                    return(true);
                }

                return(false);
            }
            else
            {
                // Since we have NOT gotten enough bytes for the whole message,
                // we need to do another receive op. Reset some variables first.

                // All of the data that we receive in the next receive op will be
                // message. None of it will be prefix. So, we need to move the
                // receiveSendToken.receiveMessageOffset to the beginning of the
                // buffer space for this SAEA.
                receiveSendToken.receiveMessageOffset = receiveSendToken.bufferOffsetReceive;
                return(false);
            }
        }
Beispiel #4
0
        public bool HandleMessage(byte[] buffer, DataHoldingUserToken receiveSendToken, ref Int32 remainingBytesToProcess)
        {
            bool incomingTcpMessageIsReady = false;

            //Create the array where we'll store the complete message,
            //if it has not been created on a previous receive op.
            if (receiveSendToken.receivedMessageBytesDoneCount == 0)
            {
                receiveSendToken.dataReceived.SetLength(receiveSendToken.lengthOfCurrentIncomingMessage);
                receiveSendToken.dataReceived.Seek(0, SeekOrigin.Begin);
            }
            // Remember there is a receiveSendToken.receivedPrefixBytesDoneCount
            // variable, which allowed us to handle the prefix even when it
            // requires multiple receive ops. In the same way, we have a
            // receiveSendToken.receivedMessageBytesDoneCount variable, which
            // helps us handle message data, whether it requires one receive
            // operation or many.
            if (remainingBytesToProcess >= receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount)
            {
                // If we are inside this if-statement, then we got
                // the end of the message. In other words,
                // the total number of bytes we received for this message matched the
                // message length value that we got from the prefix.

                // Write/append the bytes received to the byte array in the
                // DataHolder object that we are using to store our data.
                receiveSendToken.dataReceived.Write(buffer, receiveSendToken.receiveMessageOffset,
                                                    receiveSendToken.lengthOfCurrentIncomingMessage - receiveSendToken.receivedMessageBytesDoneCount);

                incomingTcpMessageIsReady = true;

                remainingBytesToProcess -=
                    receiveSendToken.lengthOfCurrentIncomingMessage -
                    receiveSendToken.receivedMessageBytesDoneCount;

                if (remainingBytesToProcess > 0)
                {
                    receiveSendToken.receiveMessageOffset +=
                        receiveSendToken.lengthOfCurrentIncomingMessage -
                        receiveSendToken.receivedMessageBytesDoneCount;
                }
                else
                {
                    receiveSendToken.receiveMessageOffset = receiveSendToken.bufferOffsetReceive;
                }
            }
            else
            {
                // If we are inside this else-statement, then that means that we
                // need another receive op. We still haven't got the whole message,
                // even though we have examined all the data that was received.
                // Not a problem. In SocketListener.ProcessReceive we will just call
                // StartReceive to do another receive op to receive more data.
                receiveSendToken.dataReceived.Write(buffer, receiveSendToken.receiveMessageOffset, remainingBytesToProcess);

                receiveSendToken.receiveMessageOffset = receiveSendToken.bufferOffsetReceive;

                receiveSendToken.receivedMessageBytesDoneCount += remainingBytesToProcess;

                remainingBytesToProcess = 0;
            }

            return(incomingTcpMessageIsReady);
        }