Ejemplo n.º 1
0
 public WebSocketFrame(
     WebSocketFin fin,
     WebSocketRsv rsv1,
     WebSocketRsv rsv2,
     WebSocketRsv rsv3,
     WebSocketOpcode opcode,
     WebSocketMask mask,
     byte[] maskingKey,
     Stream payload
     )
     : this(fin, rsv1, rsv2, rsv3, opcode, mask, maskingKey, 0, new byte[0], payload)
 {
     if (payload != null)
     {
         var len = payload.Length;
         if (len < 126)
         {
             _payloadLength    = (byte)len;
             _extPayloadLength = new byte[0];
         }
         else if (len < 0x010000)
         {
             _payloadLength    = (byte)126;
             _extPayloadLength = WebSocketUtils.GetBigEndianBytes((ushort)len);
         }
         else
         {
             _payloadLength    = (byte)127;
             _extPayloadLength = WebSocketUtils.GetBigEndianBytes((ulong)len);
         }
     }
 }
        /// <summary>
        ///     Buffer structure used for socket send operations.
        /// </summary>
        /// <param name="buffer">
        ///     Do note that there are not buffer attached to the structure, you have to assign one yourself using
        ///     <see cref="ISocketBuffer.SetBuffer(int,int)" />. This choice was made
        ///     to prevent unnecessary copy operations.
        /// </param>
        public void Send(ISocketBuffer buffer)
        {
            if (_message == null)
            {
                _httpMessageEncoder.Send(buffer);
            }
            else
            {
                // last send operation did not send all bytes enqueued in the buffer
                // so let's just continue until doing next message
                if (_bytesToSend > 0)
                {
                    buffer.SetBuffer(_buffer, _offset, _bytesToSend);
                    return;
                }

                var offset      = (int)_message.Payload.Position;
                var length      = (int)_message.Payload.Length;
                var frameLength = length - offset;

                var fin = WebSocketFin.Final;
                if (frameLength > WebSocketFrame.FragmentLength)
                {
                    frameLength = WebSocketFrame.FragmentLength;
                    fin         = WebSocketFin.More;
                }
                var opcode = WebSocketOpcode.Continuation;
                if (offset == 0) // first frame
                {
                    opcode = _message.Opcode;
                }

                var buff = new byte[frameLength];
                _message.Payload.Read(buff, 0, buff.Length);
                var payload = new MemoryStream(buff);

                WebSocketFrame frame = new WebSocketFrame(fin, opcode, (_handshake is IHttpRequest) ? WebSocketMask.Mask : WebSocketMask.Unmask, payload);

                using (var stream = new MemoryStream())
                {
                    var header = (int)frame.Fin;
                    header = (header << 1) + (int)frame.Rsv1;
                    header = (header << 1) + (int)frame.Rsv2;
                    header = (header << 1) + (int)frame.Rsv3;
                    header = (header << 4) + (int)frame.Opcode;
                    header = (header << 1) + (int)frame.Mask;
                    header = (header << 7) + (int)frame.PayloadLength;

                    stream.Write(WebSocketUtils.GetBigEndianBytes((ushort)header), 0, 2);

                    if (frame.PayloadLength > 125)
                    {
                        stream.Write(frame.ExtPayloadLength, 0, frame.ExtPayloadLength.Length);
                    }

                    if (frame.Mask == WebSocketMask.Mask)
                    {
                        stream.Write(frame.MaskingKey, 0, frame.MaskingKey.Length);
                        frame.Unmask();
                    }

                    _totalAmountToSend += (int)stream.Length;

                    if (frame.PayloadLength > 0)
                    {
                        frame.Payload.CopyTo(stream);
                    }

                    buffer.UserToken = _message;

                    _buffer      = stream.ToArray();
                    _bytesToSend = _buffer.Length;

                    buffer.SetBuffer(_buffer, 0, _bytesToSend);
                }
            }
        }