コード例 #1
0
        public static void SendByteArray(Session session, byte[] bytes, int length = -1, bool needmask = false)
        {
            if (session == null || bytes == null)
            {
                return;
            }

            int bufsize = length;

            if (bufsize < 0)
            {
                bufsize = bytes.Length;
            }

            WebMessage msg = new WebMessage(bytes, bufsize);

            msg.MaskFlag = needmask ? (byte)1 : (byte)0;
            session.Send(msg);
        }
コード例 #2
0
        public static WebMessage CreatePongMessage(byte[] body = null)
        {
            WebMessage msg = new WebMessage("");

            msg.MessageType = MSG_TYPE_PONG;

            if (body == null)
            {
                msg.RawContent  = null;
                msg.ContentSize = 0;
            }
            else
            {
                msg.RawContent  = (byte[])body.Clone();
                msg.ContentSize = body.Length;
            }

            return(msg);
        }
コード例 #3
0
        protected virtual bool ProcessMessage(MessageSessionData data)
        {
            if (data == null)
            {
                return(false);
            }
            string message = data.Message;

            if (message != null && message.Length > 0)
            {
                JsonMessage msg = WebMessage.ToJsonObject <JsonMessage>(message);
                if (msg != null && msg.MessageName != null && msg.MessageName.Length > 0)
                {
                    IMessageHandler handler = GetHandler(msg.MessageName);
                    if (handler != null)
                    {
                        handler.Handle(data);
                        return(true);
                    }
                }
            }
            return(false);
        }
コード例 #4
0
        protected virtual void DispatchMessage(object data)
        {
            Session session = null;

            try
            {
                if (m_MessageHandlerManager == null || data == null)
                {
                    return;
                }

                SessionContext ctx = (SessionContext)data;
                session = ctx.Session;
                WebMessage msg = (WebMessage)ctx.Data;

                if (msg.IsString())
                {
                    m_MessageHandlerManager.Dispatch(session, msg.MessageContent);
                }
                else if (msg.IsBinary())
                {
                    if (m_MessageHandlerManager.CanProcessBinary())
                    {
                        m_MessageHandlerManager.Dispatch(session, msg.RawContent);
                    }
                }
            }
            catch (Exception ex)
            {
                try
                {
                    OnError(session, Session.ERROR_RECEIVE, ex);
                }
                catch { }
            }
        }
コード例 #5
0
        public static void EncodeMessage(Session session, WebMessage msg)
        {
            // do some complex encode actions here ...

            Encoding encode = Encoding.UTF8;

            Byte[] bytes = null;

            if (msg.IsBinary())
            {
                bytes = msg.RawContent;
            }
            else if (msg.MessageContent.Length > 0)
            {
                bytes           = encode.GetBytes(msg.MessageContent);
                msg.ContentSize = bytes.Length;
            }

            if (bytes == null)
            {
                bytes = new byte[0];
            }

            if (msg.ContentSize <= 0)
            {
                msg.ContentSize = bytes.Length;                       // refresh size
            }
            if (msg.RawContent == null)
            {
                msg.RawContent = bytes;                         // refresh content
            }
            if (msg.RawContent != null && msg.ContentSize > msg.RawContent.Length)
            {
                msg.ContentSize = msg.RawContent.Length;
            }
        }
コード例 #6
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);
        }
コード例 #7
0
        public void Encode(Session session, Object message, MemoryStream stream)
        {
            if (message is WebMessage)
            {
                WebMessage msg = (WebMessage)message;

                EncodeMessage(session, msg);

                Byte[] bytes = msg.RawContent;
                if (bytes == null)
                {
                    bytes = new byte[0];
                }

                bool fin      = true;
                bool rsv1     = false;
                bool rsv2     = false;
                bool rsv3     = false;
                byte opcode   = 8; // if undefined then close it
                bool maskcode = msg.MaskFlag > 0;

                if (msg.IsString())
                {
                    opcode = 0x01;
                }
                else if (msg.IsBinary())
                {
                    opcode = 0x02;
                }
                else if (msg.IsPingFrame())
                {
                    opcode = 0x09;
                }
                else if (msg.IsPongFrame())
                {
                    opcode = 0x0A;
                }
                else if (msg.IsCloseFrame())
                {
                    opcode = 0x08;
                }

                byte payloadlength = 0;

                byte[] mask = maskcode ? new byte[4] {
                    0, 0, 0, 0
                } : new byte[0];
                byte[] extend = new byte[0];

                int length = msg.ContentSize;

                if (length < 126)
                {
                    extend        = new byte[0];
                    payloadlength = (byte)(length & 0xff);
                }
                else if (length < 65536)
                {
                    extend        = new byte[2];
                    payloadlength = 126;
                    extend[0]     = (byte)(length / 256);
                    extend[1]     = (byte)(length % 256);
                }
                else
                {
                    extend        = new byte[8];
                    payloadlength = 127;

                    int left = length;
                    int unit = 256;

                    for (int i = 7; i > 1; i--)
                    {
                        extend[i] = (byte)(left % unit);
                        left      = left / unit;

                        if (left == 0)
                        {
                            break;
                        }
                    }
                }

                byte[] headerbuffer = new byte[2] {
                    0, 0
                };

                if (fin)
                {
                    headerbuffer[0] |= 0x80;
                }
                if (rsv1)
                {
                    headerbuffer[0] |= 0x40;
                }
                if (rsv2)
                {
                    headerbuffer[0] |= 0x20;
                }
                if (rsv3)
                {
                    headerbuffer[0] |= 0x10;
                }

                headerbuffer[0] |= opcode;

                if (maskcode)
                {
                    headerbuffer[1] |= 0x80;
                }

                headerbuffer[1] |= payloadlength;

                stream.Write(headerbuffer, 0, headerbuffer.Length);
                if (extend.Length > 0)
                {
                    stream.Write(extend, 0, extend.Length);
                }
                if (mask.Length > 0)
                {
                    stream.Write(mask, 0, mask.Length);
                }

                if (mask.Length > 0)
                {
                    int masklen = mask.Length;
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        bytes[i] = (byte)(bytes[i] ^ mask[i % masklen]);
                    }
                }

                stream.Write(bytes, 0, length);
            }
            else if (message is byte[])
            {
                Encode(session, new WebMessage(message as byte[]), stream);
            }
            else if (message is string)
            {
                String   msg    = (String)message;
                Encoding encode = Encoding.UTF8;
                Byte[]   bytes  = encode.GetBytes(msg);
                stream.Write(bytes, 0, bytes.Length);
            }
        }
コード例 #8
0
 public void SendByteArray <TMessage>(Session session, TMessage obj, byte[] bytes, int length = -1)
 {
     WebMessage.SendByteArray <TMessage>(session, obj, bytes, length);
 }
コード例 #9
0
 public void SendByteArray(Session session, byte[] bytes, int length = -1)
 {
     WebMessage.SendByteArray(session, bytes, length);
 }
コード例 #10
0
 public void SendString(Session session, string str)
 {
     WebMessage.SendString(session, str);
 }
コード例 #11
0
 public void Send <TMessage>(Session session, TMessage obj)
 {
     WebMessage.Send <TMessage>(session, obj);
 }
コード例 #12
0
 public void Send <TMessage>(Session session, TMessage obj) where TMessage : class
 {
     WebMessage.Send <TMessage>(session, obj);
 }