protected bool HandleMessage(Message message) { lock (Sync) switch (message.Opcode) { case 1: OnString?.Invoke(Encoding.UTF8.GetString(message.Payload)); return(true); case 2: OnBinary?.Invoke(message.Payload); return(true); case 8: if (message.Length < 2) { FinishClose(); return(true); } ushort code = (ushort)(message.Payload[0] * 256 + message.Payload[1]); string reason = Encoding.UTF8.GetString(PrimitiveBuffer.Slice(message.Payload, 2, message.Length)); if (RecvClose && message.Length > 2) { return(false); } if (message.Length > 2) { return(FinishClose(code, reason)); } return(FinishClose(code)); case 9: OnPing?.Invoke(message.Payload); return(true); case 10: OnPong?.Invoke(message.Payload); return(true); default: return(false); } }
public static byte[] FlipMask(byte[] payload, byte[] mask) { byte[] copied = PrimitiveBuffer.Slice(payload, 0, (ulong)payload.LongLength); for (long i = 0; i < copied.LongLength; i++) { copied[i] ^= mask[i & 3]; } return(copied); }
public virtual bool SendPing(byte[] payload, ushort start, ulong end) => SendPing(PrimitiveBuffer.Slice(payload, start, end));
public virtual bool SendPing(byte[] payload, ushort start) => SendPing(PrimitiveBuffer.Slice(payload, start, (ulong)payload.LongLength));
public virtual bool Write(byte[] source, ulong start, ulong end) => Write(PrimitiveBuffer.Slice(source, start, end));
public virtual bool Write(byte[] source, ulong start) => Write(PrimitiveBuffer.Slice(source, start, (ulong)source.LongLength));
protected sealed override bool HandleWritable(byte[] source) { if (Malformed) { return(false); } char c = '\0'; ulong length, i = 0, sourceLength = (ulong)source.LongLength; for (; i < sourceLength;) { switch (State) { case ParseState.Dormant: return(false); case ParseState.Binary: ContentLength = EncodedContentLength += sourceLength; if (!WriteChunk(source)) { return(false); } if (Type.Value.Length.HasValue && Type.Value.Length == ContentLength) { return(Finish()); } return(true); case ParseState.Chunked_Length: EncodedContentLength++; c = (char)source[i++]; if (c == CR) { State = ParseState.Chunked_LengthLf; } else { ChunkLengthString = ChunkLengthString == null?c.ToString() : ChunkLengthString + c; } break; case ParseState.Chunked_LengthLf: EncodedContentLength++; c = (char)source[i++]; if (c != LF) { return(!(Malformed = true)); } ChunkIndex = 0; if (!ulong.TryParse(ChunkLengthString, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out length)) { return(!(Malformed = true)); } ChunkLengthString = null; State = (ChunkLength = length) == 0 ? ParseState.Chunked_Trailer : ParseState.Chunked_ChunkData; break; case ParseState.Chunked_ChunkData: length = Math.Min(ChunkLength - ChunkIndex, sourceLength - i); WriteChunk(PrimitiveBuffer.Slice(source, i, i += length)); ChunkIndex += length; ContentLength += length; EncodedContentLength += length; if (ChunkIndex >= ChunkLength) { State = ParseState.Chunked_ChunkCr; } break; case ParseState.Chunked_ChunkCr: EncodedContentLength++; c = (char)source[i++]; if (c != CR) { return(!(Malformed = true)); } State = ParseState.Chunked_ChunkLf; break; case ParseState.Chunked_ChunkLf: EncodedContentLength++; c = (char)source[i++]; if (c != LF) { return(!(Malformed = true)); } ChunkIndex = 0; State = ParseState.Chunked_Length; break; case ParseState.Chunked_Trailer: while ((c = (char)source[i++]) != CR) { EncodedContentLength++; } State = ParseState.Chunked_Lf; break; case ParseState.Chunked_Lf: EncodedContentLength++; c = (char)source[i++]; if (c != LF) { return(!(Malformed = true)); } ExcessStore.Write(source, i); return(Finish()); } } return(true); }
protected override bool HandleWritable(byte[] source) { if (Malformed) { return(false); } ulong i = 0, sourceLength = (ulong)source.LongLength; for (char c; i < sourceLength; i++) { c = (char)source[i]; switch (State) { case ParseState.Version: if (c != WS) { IncomingVersion += c; } else { if (!Version.TryParse(IncomingVersion, out Version result)) { return(!(Malformed = true)); } IncomingVersionValue = result; State = ParseState.StatusCode; } break; case ParseState.StatusCode: if (c == WS) { State = ParseState.StatusDescription; } else if (char.IsDigit(c)) { IncomingStatusCode += c; } else { return(!(Malformed = true)); } break; case ParseState.StatusDescription: if (c != CR) { IncomingStatusDescription += c; } else { State = ParseState.FirstLf; } break; case ParseState.FirstLf: if (c != LF) { return(!(Malformed = true)); } State = ParseState.HeaderName; break; case ParseState.HeaderName: if (c == CR) { State = ParseState.Lf; } else if (c != COLON) { IncomingHeaderName += c; } else { State = ParseState.HeaderValue; } break; case ParseState.HeaderValue: if (c != CR) { IncomingHeaderValue += c; } else { IncomingHeaders.Add(IncomingHeaderName, IncomingHeaderValue.TrimStart()); IncomingHeaderName = ""; IncomingHeaderValue = ""; State = ParseState.HeaderLf; } break; case ParseState.HeaderLf: if (c != LF) { return(!(Malformed = true)); } else { State = ParseState.HeaderName; } break; case ParseState.Lf: if (c != LF) { return(!(Malformed = true)); } HandleReadable(PrimitiveBuffer.Slice(source, i + 1, sourceLength)); Pickup(new ResponseHead(IncomingVersionValue, ushort.Parse(IncomingStatusCode), IncomingStatusDescription, IncomingHeaders)); return(Reset()); } } return(true); }