예제 #1
0
        private static WebSocketFrame read(byte[] header, Stream stream, bool unmask)
        {
            /* Header */

            // FIN
            var fin = (header[0] & 0x80) == 0x80 ? Fin.Final : Fin.More;
            // RSV1
            var rsv1 = (header[0] & 0x40) == 0x40 ? Rsv.On : Rsv.Off;
            // RSV2
            var rsv2 = (header[0] & 0x20) == 0x20 ? Rsv.On : Rsv.Off;
            // RSV3
            var rsv3 = (header[0] & 0x10) == 0x10 ? Rsv.On : Rsv.Off;
            // Opcode
            var opcode = (Opcode)(header[0] & 0x0f);
            // MASK
            var mask = (header[1] & 0x80) == 0x80 ? Mask.Mask : Mask.Unmask;
            // Payload Length
            var payloadLen = (byte)(header[1] & 0x7f);

            // Check if valid header
            var err = isControl(opcode) && payloadLen > 125
                ? "A control frame has a payload data which is greater than the allowable max size."
                : isControl(opcode) && fin == Fin.More
                  ? "A control frame is fragmented."
                  : !isData(opcode) && rsv1 == Rsv.On
                    ? "A non data frame is compressed."
                    : null;

            if (err != null)
            {
                throw new WebSocketException(CloseStatusCode.ProtocolError, err);
            }

            var frame = new WebSocketFrame();

            frame._fin           = fin;
            frame._rsv1          = rsv1;
            frame._rsv2          = rsv2;
            frame._rsv3          = rsv3;
            frame._opcode        = opcode;
            frame._mask          = mask;
            frame._payloadLength = payloadLen;

            /* Extended Payload Length */

            var size = payloadLen < 126
                 ? 0
                 : payloadLen == 126
                   ? 2
                   : 8;

            var extPayloadLen = size > 0 ? stream.ReadBytes(size) : new byte[0];

            if (size > 0 && extPayloadLen.Length != size)
            {
                throw new WebSocketException(
                          "The 'Extended Payload Length' of a frame cannot be read from the data source.");
            }

            frame._extPayloadLength = extPayloadLen;

            /* Masking Key */

            var masked     = mask == Mask.Mask;
            var maskingKey = masked ? stream.ReadBytes(4) : new byte[0];

            if (masked && maskingKey.Length != 4)
            {
                throw new WebSocketException(
                          "The 'Masking Key' of a frame cannot be read from the data source.");
            }

            frame._maskingKey = maskingKey;

            /* Payload Data */

            ulong len = payloadLen < 126
                  ? payloadLen
                  : payloadLen == 126
                    ? extPayloadLen.ToUInt16(ByteOrder.Big)
                    : extPayloadLen.ToUInt64(ByteOrder.Big);

            byte[] data = null;
            if (len > 0)
            {
                // Check if allowable max length.
                if (payloadLen > 126 && len > PayloadData.MaxLength)
                {
                    throw new WebSocketException(
                              CloseStatusCode.TooBig,
                              "The length of 'Payload Data' of a frame is greater than the allowable max length.");
                }

                data = payloadLen > 126
               ? stream.ReadBytes((long)len, 1024)
               : stream.ReadBytes((int)len);

                if (data.LongLength != (long)len)
                {
                    throw new WebSocketException(
                              "The 'Payload Data' of a frame cannot be read from the data source.");
                }
            }
            else
            {
                data = new byte[0];
            }

            frame._payloadData = new PayloadData(data, masked);
            if (unmask && masked)
            {
                frame.Unmask();
            }

            return(frame);
        }
예제 #2
0
 internal MessageEventArgs(WebSocketFrame frame)
 {
     _opcode  = frame.Opcode;
     _rawData = frame.PayloadData.ApplicationData;
     _data    = convertToString(_opcode, _rawData);
 }
예제 #3
0
        private static string dump(WebSocketFrame frame)
        {
            var len = frame.Length;
            var cnt = (long)(len / 4);
            var rem = (int)(len % 4);

            int    cntDigit;
            string cntFmt;

            if (cnt < 10000)
            {
                cntDigit = 4;
                cntFmt   = "{0,4}";
            }
            else if (cnt < 0x010000)
            {
                cntDigit = 4;
                cntFmt   = "{0,4:X}";
            }
            else if (cnt < 0x0100000000)
            {
                cntDigit = 8;
                cntFmt   = "{0,8:X}";
            }
            else
            {
                cntDigit = 16;
                cntFmt   = "{0,16:X}";
            }

            var spFmt     = String.Format("{{0,{0}}}", cntDigit);
            var headerFmt = String.Format(@"
{0} 01234567 89ABCDEF 01234567 89ABCDEF
{0}+--------+--------+--------+--------+\n", spFmt);
            var lineFmt   = String.Format("{0}|{{1,8}} {{2,8}} {{3,8}} {{4,8}}|\n", cntFmt);
            var footerFmt = String.Format("{0}+--------+--------+--------+--------+", spFmt);

            var output = new StringBuilder(64);
            Func <Action <string, string, string, string> > linePrinter = () => {
                long lineCnt = 0;
                return((arg1, arg2, arg3, arg4) =>
                       output.AppendFormat(lineFmt, ++lineCnt, arg1, arg2, arg3, arg4));
            };

            output.AppendFormat(headerFmt, String.Empty);

            var printLine = linePrinter();
            var bytes     = frame.ToByteArray();

            for (long i = 0; i <= cnt; i++)
            {
                var j = i * 4;
                if (i < cnt)
                {
                    printLine(
                        Convert.ToString(bytes[j], 2).PadLeft(8, '0'),
                        Convert.ToString(bytes[j + 1], 2).PadLeft(8, '0'),
                        Convert.ToString(bytes[j + 2], 2).PadLeft(8, '0'),
                        Convert.ToString(bytes[j + 3], 2).PadLeft(8, '0'));
                }
                else if (rem > 0)
                {
                    printLine(
                        Convert.ToString(bytes[j], 2).PadLeft(8, '0'),
                        rem >= 2 ? Convert.ToString(bytes[j + 1], 2).PadLeft(8, '0') : String.Empty,
                        rem == 3 ? Convert.ToString(bytes[j + 2], 2).PadLeft(8, '0') : String.Empty,
                        String.Empty);
                }
            }

            output.AppendFormat(footerFmt, String.Empty);
            return(output.ToString());
        }