示例#1
0
        public override void OnConnect(Session session)
        {
            WebMessage.GetSessionBuffer(session, true);
            WebMessage.GetSessionData(session, true);

            if (IsOrderlyProcess)
            {
                WebMessage.GetSingleTaskFactory(session, true);
            }

            base.OnConnect(session);
        }
示例#2
0
        // please know that function Decode() should be called in single thread
        public bool Decode(Session session, MemoryStream stream, List <Object> output)
        {
            bool       isNew  = false;
            WebMessage netMsg = null;

            bool           hasKey = false;
            Stack <Object> stack  = WebMessage.GetSessionBuffer(session);

            if (stack.Count > 0)
            {
                hasKey = true;
                netMsg = (WebMessage)stack.Peek();
            }
            if (netMsg == null)
            {
                isNew  = true;
                netMsg = new WebMessage();
                if (hasKey)
                {
                    stack.Pop();
                }
                stack.Push(netMsg);
            }

            if (isNew)
            {
                if (netMsg != null)
                {
                    netMsg.ReceivingState = WebMessage.STATE_WAIT_FOR_BODY;
                    netMsg.MessageType    = WebMessage.MSG_TYPE_HANDSHAKE;
                }
            }

            int total = 0;

            if (netMsg.ReceivingState == WebMessage.STATE_WAIT_FOR_BODY)
            {
                if (netMsg.MessageType == WebMessage.MSG_TYPE_HANDSHAKE)
                {
                    long orgpos = stream.Position;
                    long msglen = stream.Length - stream.Position;

                    Byte[] bytes = new Byte[msglen];
                    stream.Read(bytes, 0, bytes.Length);

                    bool found = false;

                    int curpos     = 0;
                    int maxpos     = bytes.Length - 1;
                    int checkedlen = 0;
                    while (curpos <= maxpos && !found)
                    {
                        if (bytes[curpos] == '\r')
                        {
                            if (curpos + 1 <= maxpos && bytes[curpos + 1] == '\n')
                            {
                                if (curpos + 2 <= maxpos && bytes[curpos + 2] == '\r')
                                {
                                    if (curpos + 3 <= maxpos && bytes[curpos + 3] == '\n')
                                    {
                                        found      = true;
                                        checkedlen = curpos + 3 + 1;
                                    }
                                }
                            }
                        }

                        curpos++;
                    }

                    if (found)
                    {
                        Encoding encode        = Encoding.UTF8;
                        string   headerContent = encode.GetString(bytes, 0, checkedlen);

                        string[] rawClientHandshakeLines = headerContent.Split(new string[] { "\r\n" },
                                                                               System.StringSplitOptions.RemoveEmptyEntries);
                        string acceptKey       = "";
                        bool   foundKey        = false;
                        bool   foundUrl        = false;
                        bool   foundServerSign = false;

                        string handshakeMsg = "";

                        foreach (string oneline in rawClientHandshakeLines)
                        {
                            if (!foundUrl && oneline.Contains(HTTP_HEADER_SIGN))
                            {
                                if (oneline.Contains(HTTP_SERVER_HEADER_SIGN))
                                {
                                    foundServerSign = true;
                                }
                                else
                                {
                                    string reqline  = oneline.Trim();
                                    int    beginPos = reqline.IndexOf(' ') + 1;
                                    int    endPos   = reqline.LastIndexOf(' ');
                                    if (beginPos > 0 && endPos > beginPos)
                                    {
                                        WebMessage.SetSessionData(session, "Path", reqline.Substring(beginPos, endPos - beginPos).Trim());
                                    }
                                }
                                foundUrl = true;
                            }

                            if (!foundKey && !foundServerSign && oneline.Contains(WEBSOCK_CLIENT_HEADER_SIGN + ":"))
                            {
                                acceptKey = ComputeWebSocketHandshakeSecurityHash09(oneline.Substring(oneline.IndexOf(":") + 2));
                                foundKey  = true;
                            }
                        }

                        if (acceptKey != null && acceptKey.Length > 0)
                        {
                            handshakeMsg = String.Format(WEBSOCK_HANDSHAKE_REPLY_MSG, acceptKey);
                        }

                        stream.Position = orgpos + checkedlen;

                        netMsg.ReceivingState = WebMessage.STATE_READY;
                        if (stack.Count > 0)
                        {
                            stack.Pop();
                        }

                        netMsg.MessageContent = headerContent;
                        netMsg.MessageType    = WebMessage.MSG_TYPE_HANDSHAKE;
                        output.Add(netMsg);
                        total++;

                        netMsg = new WebMessage();
                        netMsg.VirtualHeaderSize = 2;
                        stack.Push(netMsg);

                        if (handshakeMsg != null && handshakeMsg.Length > 0)
                        {
                            session.Send(handshakeMsg);
                        }
                    }
                    else
                    {
                        if (curpos > m_MaxMsgSize)
                        {
                            session.Close();
                        }
                        else
                        {
                            stream.Position = orgpos;
                        }
                        return(false);
                    }
                }

                if (netMsg.ReceivingState == WebMessage.STATE_WAIT_FOR_BODY &&
                    stream.Length - stream.Position >= netMsg.ContentSize)
                {
                    Byte[] bytes = new Byte[netMsg.ContentSize];
                    stream.Read(bytes, 0, netMsg.ContentSize);

                    if (netMsg.MaskFlag > 0 && netMsg.MaskBytes != null)
                    {
                        int masklen = netMsg.MaskBytes.Length;
                        for (int i = 0; i < bytes.Length; i++)
                        {
                            bytes[i] = (byte)(bytes[i] ^ netMsg.MaskBytes[i % masklen]);
                        }
                    }

                    if (netMsg.MessageType == WebMessage.MSG_TYPE_STRING)
                    {
                        netMsg.MessageContent = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                    }

                    if (netMsg.MessageType == WebMessage.MSG_TYPE_BINARY ||
                        netMsg.MessageType == WebMessage.MSG_TYPE_PING ||
                        netMsg.MessageType == WebMessage.MSG_TYPE_PONG)
                    {
                        netMsg.RawContent  = bytes;
                        netMsg.ContentSize = bytes.Length;
                    }

                    output.Add(netMsg);
                    total++;

                    netMsg.ReceivingState = WebMessage.STATE_READY;
                    if (stack.Count > 0)
                    {
                        stack.Pop();
                    }

                    netMsg = new WebMessage();
                    netMsg.VirtualHeaderSize = 2;
                    stack.Push(netMsg);
                }
            }

            while (netMsg.ReceivingState == WebMessage.STATE_WAIT_FOR_HEADER &&
                   stream.Length - stream.Position >= netMsg.VirtualHeaderSize)
            {
                if (netMsg.ReceivingState == WebMessage.STATE_WAIT_FOR_HEADER)
                {
                    if (stream.Length - stream.Position >= netMsg.VirtualHeaderSize)
                    {
                        Byte[] bytes = new Byte[netMsg.VirtualHeaderSize];
                        stream.Read(bytes, 0, netMsg.VirtualHeaderSize);

                        if (netMsg.VirtualHeaderSize == 2)
                        {
                            // first byte ...
                            sbyte opcode = (sbyte)(bytes[0] & 0x0f);

                            switch (opcode) // not support 0x00 for now ...
                            {
                            case 0x08:
                                session.Close();
                                return(false);

                            case 0x09:
                                netMsg.MessageType = WebMessage.MSG_TYPE_PING;
                                break;

                            case 0x0A:
                                netMsg.MessageType = WebMessage.MSG_TYPE_PONG;
                                break;

                            case 0x01:
                                netMsg.MessageType = WebMessage.MSG_TYPE_STRING;
                                break;

                            case 0x02:
                                netMsg.MessageType = WebMessage.MSG_TYPE_BINARY;
                                break;

                            default:
                                session.Close();     // just close it if undefined op code found
                                return(false);
                            }

                            bool needmask = (bytes[1] & 0x80) == 0x80;

                            if (needmask)
                            {
                                netMsg.VirtualHeaderSize += 4;
                                netMsg.MaskFlag           = 1;
                            }
                            else
                            {
                                netMsg.MaskFlag = 0;
                            }

                            sbyte payloadlen = (sbyte)(bytes[1] & 0x7f);

                            if (payloadlen == 126)
                            {
                                netMsg.VirtualHeaderSize += 2;
                                netMsg.HeaderFlag         = 1;
                            }
                            else if (payloadlen == 127)
                            {
                                netMsg.VirtualHeaderSize += 8;
                                netMsg.HeaderFlag         = 2;
                            }
                            else
                            {
                                netMsg.HeaderFlag = 0;
                            }
                        }

                        if (netMsg.VirtualHeaderSize > bytes.Length)
                        {
                            stream.Position = stream.Position - bytes.Length;
                            continue;
                        }

                        if (netMsg.MaskFlag > 0)
                        {
                            netMsg.MaskBytes = new byte[4];
                            Buffer.BlockCopy(bytes, netMsg.VirtualHeaderSize - 4, netMsg.MaskBytes, 0, 4);
                        }

                        if (netMsg.HeaderFlag == 1)
                        {
                            netMsg.ContentSize = (int)bytes[2] * 256 + (int)bytes[3];
                        }
                        else if (netMsg.HeaderFlag == 2)
                        {
                            long len = 0;
                            int  n   = 1;
                            for (int i = 7; i >= 0; i--)
                            {
                                len += (int)bytes[i + 2] * n;
                                n   *= 256;
                            }

                            netMsg.ContentSize = (int)len;
                        }
                        else
                        {
                            netMsg.ContentSize = (sbyte)(bytes[1] & 0x7f);
                        }

                        if (netMsg.ContentSize > m_MaxMsgSize)
                        {
                            netMsg.ContentSize = 0;
                        }
                        if (netMsg.ContentSize < 0)
                        {
                            netMsg.ContentSize = 0;
                        }

                        if (netMsg.ContentSize > 0)
                        {
                            netMsg.ReceivingState = WebMessage.STATE_WAIT_FOR_BODY;
                        }
                        else
                        {
                            netMsg.ReceivingState = WebMessage.STATE_READY;
                            if (stack.Count > 0)
                            {
                                stack.Pop();
                            }

                            netMsg = new WebMessage();
                            netMsg.VirtualHeaderSize = 2;
                            stack.Push(netMsg);

                            continue;
                        }
                    }
                }

                if (netMsg.ReceivingState == WebMessage.STATE_WAIT_FOR_BODY)
                {
                    if (stream.Length - stream.Position >= netMsg.ContentSize)
                    {
                        Byte[] bytes = new Byte[netMsg.ContentSize];
                        stream.Read(bytes, 0, netMsg.ContentSize);

                        if (netMsg.MaskFlag > 0 && netMsg.MaskBytes != null)
                        {
                            int masklen = netMsg.MaskBytes.Length;
                            for (int i = 0; i < bytes.Length; i++)
                            {
                                bytes[i] = (byte)(bytes[i] ^ netMsg.MaskBytes[i % masklen]);
                            }
                        }

                        if (netMsg.MessageType == WebMessage.MSG_TYPE_STRING)
                        {
                            netMsg.MessageContent = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                        }

                        if (netMsg.MessageType == WebMessage.MSG_TYPE_BINARY ||
                            netMsg.MessageType == WebMessage.MSG_TYPE_PING ||
                            netMsg.MessageType == WebMessage.MSG_TYPE_PONG)
                        {
                            netMsg.RawContent  = bytes;
                            netMsg.ContentSize = bytes.Length;
                        }

                        output.Add(netMsg);
                        total++;

                        netMsg.ReceivingState = WebMessage.STATE_READY;
                        if (stack.Count > 0)
                        {
                            stack.Pop();
                        }

                        netMsg = new WebMessage();
                        netMsg.VirtualHeaderSize = 2;
                        stack.Push(netMsg);
                    }
                }
            }

            if (total > 0 && stream.Length - stream.Position <= 0)
            {
                return(true);
            }

            if (netMsg.ReceivingState != WebMessage.STATE_WAIT_FOR_HEADER &&
                netMsg.ReceivingState != WebMessage.STATE_WAIT_FOR_BODY &&
                netMsg.ReceivingState != WebMessage.STATE_READY)
            {
                session.Close();
            }

            return(false);
        }