internal static Task WriteAsync <T>(WebSocketConnection connection, WebSocketsFrame.OpCodes opCode, WebSocketsFrame.FrameFlags flags, ref T message) where T : struct, IMessageWriter { int payloadLength = message.GetPayloadLength(); var buffer = connection.Connection.Output.Alloc(MaxHeaderLength + payloadLength); int mask = connection.ConnectionType == ConnectionType.Client ? CreateMask() : 0; WriteFrameHeader(ref buffer, WebSocketsFrame.FrameFlags.IsFinal, opCode, payloadLength, mask); if (payloadLength != 0) { if (mask == 0) { message.WritePayload(buffer); } else { var payloadStart = buffer.AsReadableBuffer().End; message.WritePayload(buffer); var payload = buffer.AsReadableBuffer().Slice(payloadStart); // note that this is a different AsReadableBuffer; call twice is good WebSocketsFrame.ApplyMask(ref payload, mask); } } return(buffer.FlushAsync().AsTask()); }
internal static void WriteFrameHeader(ref WritableBuffer output, WebSocketsFrame.FrameFlags flags, WebSocketsFrame.OpCodes opCode, int payloadLength, int mask) { output.Ensure(MaxHeaderLength); int index = 0; var span = output.Buffer.Span; span[index++] = (byte)(((int)flags & 240) | ((int)opCode & 15)); if (payloadLength > ushort.MaxValue) { // write as a 64-bit length span[index++] = (byte)((mask != 0 ? 128 : 0) | 127); span.Slice(index).Write((uint)0); span.Slice(index + 4).Write(ToNetworkByteOrder((uint)payloadLength)); index += 8; } else if (payloadLength > 125) { // write as a 16-bit length span[index++] = (byte)((mask != 0 ? 128 : 0) | 126); span.Slice(index).Write(ToNetworkByteOrder((ushort)payloadLength)); index += 2; } else { // write in the header span[index++] = (byte)((mask != 0 ? 128 : 0) | payloadLength); } if (mask != 0) { span.Slice(index).Write(mask); index += 4; } output.Advance(index); }
internal Task SendAsync(WebSocketsFrame.OpCodes opCode, ref Message message, WebSocketsFrame.FrameFlags flags = WebSocketsFrame.FrameFlags.IsFinal) { if (connection.Output.Writing.IsCompleted) { throw new InvalidOperationException("Connection has been closed"); } return(SendAsyncImpl(opCode, message, flags)); }
public Task SendAsync(byte[] message, WebSocketsFrame.FrameFlags flags = WebSocketsFrame.FrameFlags.IsFinal) { if (message == null) { throw new ArgumentNullException(nameof(message)); } var msg = MessageWriter.Create(message); return(SendAsync(WebSocketsFrame.OpCodes.Binary, ref msg, flags)); }
internal static unsafe void WriteFrameHeader(ref WritableBuffer output, WebSocketsFrame.FrameFlags flags, WebSocketsFrame.OpCodes opCode, int payloadLength, int mask) { byte *buffer = (byte *)output.Memory.BufferPtr; int bytesWritten; *buffer++ = (byte)(((int)flags & 240) | ((int)opCode & 15)); if (payloadLength > ushort.MaxValue) { // write as a 64-bit length *buffer++ = (byte)((mask != 0 ? 128 : 0) | 127); *buffer++ = 0; *buffer++ = 0; *buffer++ = 0; *buffer++ = 0; *buffer++ = (byte)(payloadLength >> 24); *buffer++ = (byte)(payloadLength >> 16); *buffer++ = (byte)(payloadLength >> 8); *buffer++ = (byte)(payloadLength); bytesWritten = 10; } else if (payloadLength > 125) { // write as a 16-bit length *buffer++ = (byte)((mask != 0 ? 128 : 0) | 126); *buffer++ = (byte)(payloadLength >> 8); *buffer++ = (byte)(payloadLength); bytesWritten = 4; } else { // write in the header *buffer++ = (byte)((mask != 0 ? 128 : 0) | payloadLength); bytesWritten = 2; } if (mask != 0) { *buffer++ = (byte)(mask >> 24); *buffer++ = (byte)(mask >> 16); *buffer++ = (byte)(mask >> 8); *buffer++ = (byte)(mask); bytesWritten += 4; } output.CommitBytes(bytesWritten); }
private async Task SendAsyncImpl <T>(WebSocketsFrame.OpCodes opCode, T message, WebSocketsFrame.FrameFlags flags) where T : struct, IMessageWriter { //TODO: come up with a better way of getting ordered access to the socket var writeLock = GetWriteSemaphore(); bool haveLock = writeLock.Wait(0); if (!haveLock) { // try to acquire asynchronously instead, then await writeLock.WaitAsync(); } try { WebSocketServer.WriteStatus(ConnectionType, $"Writing {opCode} message ({message.GetPayloadLength()} bytes)..."); await WebSocketProtocol.WriteAsync(this, opCode, flags, ref message); if (opCode == WebSocketsFrame.OpCodes.Close) { connection.Output.Complete(); } } finally { writeLock.Release(); } }
internal Task SendAsync <T>(WebSocketsFrame.OpCodes opCode, ref T message, WebSocketsFrame.FrameFlags flags = WebSocketsFrame.FrameFlags.IsFinal) where T : struct, IMessageWriter { return(SendAsyncImpl(opCode, message, flags)); }