protected void ProcessBinary(NetContext context, Connection connection) { if (incoming == null) { return; } byte[] value; incoming.Position = 0; using (incoming) { value = new byte[incoming.Length]; NetContext.Fill(incoming, value, (int)incoming.Length); } incoming = null; context.Handler.OnReceived(connection, value); }
protected override int ProcessIncoming(NetContext context, Connection connection, Stream incomingBuffer) { int len = FindHeadersLength(incomingBuffer); if (len <= 0) { return(0); } incomingBuffer.Position = 0; int extraConsumed; if (len < NetContext.BufferSize) { byte[] buffer = null; try { buffer = context.GetBuffer(); NetContext.Fill(incomingBuffer, buffer, len); using (var ms = new MemoryStream(buffer, 0, len)) { extraConsumed = ProcessHeadersAndUpgrade(context, connection, ms, incomingBuffer, len); } } finally { context.Recycle(buffer); } } else { using (var ss = new SubStream(incomingBuffer, len)) { extraConsumed = ProcessHeadersAndUpgrade(context, connection, ss, incomingBuffer, len); } } if (extraConsumed < 0) { return(0); // means: wasn't usable (yet) } return(len + extraConsumed); }
protected override int ProcessIncoming(NetContext context, Connection connection, Stream incoming) { if (keys != null) // handshake is not yet complete { if (incoming.Length < 8) { return(0); // need 8 bytes to finish the handshake } var key3 = new byte[8]; NetContext.Fill(incoming, key3, 8); // now that we're on a different protocol, send the server's response to the client's challenge var securityCheck = ComputeKey(keys.Item1, keys.Item2, key3); keys = null; // wipe SendControl(context, new BinaryFrame(securityCheck)); connection.PromptToSend(context); return(8); } return(base.ProcessIncoming(context, connection, incoming)); }
protected override int ProcessIncoming(NetContext context, Connection connection, Stream incoming) { if (expectedResponse != null) { if (incoming.Length < expectedResponse.Length) { return(0); // not enough to check the response } byte[] actual = new byte[expectedResponse.Length]; NetContext.Fill(incoming, actual, actual.Length); for (int i = 0; i < actual.Length; i++) { if (actual[i] != expectedResponse[i]) { throw new InvalidOperationException("Incorrect Hixie76 respoonse"); } } expectedResponse = null; // all verified now return(actual.Length); // the amount we processed } return(base.ProcessIncoming(context, connection, incoming)); }
protected override int ProcessIncoming(NetContext context, Connection connection, System.IO.Stream incoming) { if (incoming.Length < 2) { return(0); // can't read that; start/end markers take at least 2 bytes } switch (incoming.ReadByte()) { case 0x00: var ws = (WebSocketConnection)connection; if (!ws.AllowIncomingDataFrames) { throw new InvalidOperationException("Data frames disabled"); } // data frame is 0x00 [data] 0xFF int len = 0, cur; while ((cur = incoming.ReadByte()) != 0xFF && cur >= 0) { len++; } if (cur < 0) { throw new EndOfStreamException(); } incoming.Position = 1; string value; if (len == 0) { value = ""; } else if (len <= NetContext.BufferSize) { byte[] buffer = null; try { buffer = context.GetBuffer(); NetContext.Fill(incoming, buffer, len); value = Encoding.UTF8.GetString(buffer, 0, len); } finally { context.Recycle(buffer); } } else { var buffer = new byte[len]; NetContext.Fill(incoming, buffer, len); value = Encoding.UTF8.GetString(buffer, 0, len); } context.Handler.OnReceived(connection, value); return(len + 2); case 0xFF: // shutdown is 0xFF 0x00 if (incoming.ReadByte() == 0x00) { GracefulShutdown(context, connection); return(2); } else { throw new InvalidOperationException("protocol fail"); } default: throw new InvalidOperationException("protocol fail"); } }
IEnumerable <WebSocketsFrame> IExtension.ApplyOutgoing(NetContext context, WebSocketConnection connection, WebSocketsFrame frame) { if (!frame.IsControlFrame && frame.PayloadLength > parent.compressMessagesLargerThanBytes) { if (frame.Reserved1) { throw new InvalidOperationException("Reserved1 flag is already set; extension conflict?"); } int headerBytes = 0; if (outbound == null) { outbound = new ZStream(); const int BITS = 12; // 4096 byte outbound buffer (instead of full 32k=15) outbound.deflateInit(zlibConst.Z_BEST_COMPRESSION, BITS); headerBytes = 2; } BufferStream tmp = null; var payload = frame.Payload; payload.Position = 0; byte[] inBuffer = null, outBuffer = null; try { inBuffer = context.GetBuffer(); outBuffer = context.GetBuffer(); tmp = new BufferStream(context, 0); outbound.next_out = outBuffer; outbound.next_in = inBuffer; int remaining = frame.PayloadLength; while (remaining > 0) { int readCount = payload.Read(inBuffer, 0, inBuffer.Length); if (readCount <= 0) { break; } remaining -= readCount; outbound.next_in_index = 0; outbound.avail_in = readCount; do { outbound.next_out_index = 0; outbound.avail_out = outBuffer.Length; long priorOut = outbound.total_out; int err = outbound.deflate(remaining == 0 ? zlibConst.Z_SYNC_FLUSH : zlibConst.Z_NO_FLUSH); if (err != zlibConst.Z_OK && err != zlibConst.Z_STREAM_END) { throw new ZStreamException("deflating: " + outbound.msg); } int outCount = (int)(outbound.total_out - priorOut); if (outCount > 0) { if (headerBytes == 0) { tmp.Write(outBuffer, 0, outCount); } else { if (outCount < headerBytes) { throw new InvalidOperationException("Failed to write entire header"); } // check the generated header meets our expectations // CMF is very specific - CM must be 8, and CINFO must be <=7 (for 32k window) if ((outBuffer[0] & 15) != 8) { throw new InvalidOperationException("Zlib CM header was incorrect"); } if ((outBuffer[0] & 128) != 0) // if msb set, is > 7 - invalid { throw new InvalidOperationException("Zlib CINFO header was incorrect"); } // FLG is less important; FCHECK is irrelevent, FLEVEL doesn't matter; but // FDICT must be zero, to ensure that we aren't expecting a an initialization dictionary if ((outBuffer[1] & 32) != 0) { throw new InvalidOperationException("Zlib FLG.FDICT header was set (must not be)"); } // skip the header, and write anything else outCount -= headerBytes; if (outCount > 0) { tmp.Write(outBuffer, headerBytes, outCount); } headerBytes = 0; // all written now } } } while (outbound.avail_in > 0 || outbound.avail_out == 0); } if (remaining != 0) { throw new EndOfStreamException(); } if (headerBytes != 0) { throw new InvalidOperationException("Zlib header was not written"); } // verify the last 4 bytes, then drop them tmp.Position = tmp.Length - 4; NetContext.Fill(tmp, outBuffer, 4); if (!(outBuffer[0] == 0x00 && outBuffer[1] == 0x00 && outBuffer[2] == 0xFF && outBuffer[3] == 0xFF)) { throw new InvalidOperationException("expectation failed: 0000FFFF in the tail"); } if (parent.disableContextTakeover && tmp.Length >= frame.PayloadLength) { // compressing it didn't do anything useful; since we're going to discard // the compression context, we might as well stick with the original data payload.Position = 0; payload = null; // so that it doesn't get disposed } else { // set our final output tmp.Position = 0; tmp.SetLength(tmp.Length - 4); long bytesSaved = frame.PayloadLength - tmp.Length; frame.Payload = tmp; frame.PayloadLength = (int)tmp.Length; frame.Reserved1 = true; tmp = payload as BufferStream; parent.RegisterOutboundBytesSaved(bytesSaved); } } #if DEBUG catch (Exception ex) { Debug.WriteLine(ex); throw; } #endif finally { if (outbound != null) { outbound.next_out = null; outbound.next_in = null; } if (tmp != null) { tmp.Dispose(); } if (inBuffer != null) { context.Recycle(inBuffer); } if (outBuffer != null) { context.Recycle(outBuffer); } if (parent.disableContextTakeover) { ClearContext(false, true); } } } yield return(frame); }