private IoBuffer InsertBytesToNewIoBuffer(IoSession session, IoBuffer buffer) { if (_insertByteProbability > _rng.Next(1000)) { if (log.IsInfoEnabled) { log.Info(buffer.GetHexDump()); } // where to insert bytes ? int pos = _rng.Next(buffer.Remaining) - 1; // how many byte to insert ? int count = _rng.Next(_maxInsertByte - 1) + 1; IoBuffer newBuff = IoBuffer.Allocate(buffer.Remaining + count); for (int i = 0; i < pos; i++) { newBuff.Put(buffer.Get()); } for (int i = 0; i < count; i++) { newBuff.Put((byte)(_rng.Next(256))); } while (buffer.Remaining > 0) { newBuff.Put(buffer.Get()); } newBuff.Flip(); if (log.IsInfoEnabled) { log.Info("Inserted " + count + " bytes."); log.Info(newBuff.GetHexDump()); } return(newBuff); } return(null); }
private void ManipulateIoBuffer(IoSession session, IoBuffer buffer) { if ((buffer.Remaining > 0) && (_removeByteProbability > _rng.Next(1000))) { if (log.IsInfoEnabled) { log.Info(buffer.GetHexDump()); } // where to remove bytes ? int pos = _rng.Next(buffer.Remaining); // how many byte to remove ? int count = _rng.Next(buffer.Remaining - pos) + 1; if (count == buffer.Remaining) { count = buffer.Remaining - 1; } IoBuffer newBuff = IoBuffer.Allocate(buffer.Remaining - count); for (int i = 0; i < pos; i++) { newBuff.Put(buffer.Get()); } buffer.Skip(count); // hole while (newBuff.Remaining > 0) { newBuff.Put(buffer.Get()); } newBuff.Flip(); // copy the new buffer in the old one buffer.Rewind(); buffer.Put(newBuff); buffer.Flip(); if (log.IsInfoEnabled) { log.Info("Removed " + count + " bytes at position " + pos + "."); log.Info(buffer.GetHexDump()); } } if ((buffer.Remaining > 0) && (_changeByteProbability > _rng.Next(1000))) { if (log.IsInfoEnabled) { log.Info(buffer.GetHexDump()); } // how many byte to change ? int count = _rng.Next(buffer.Remaining - 1) + 1; byte[] values = new byte[count]; _rng.NextBytes(values); for (int i = 0; i < values.Length; i++) { int pos = _rng.Next(buffer.Remaining); buffer.Put(pos, values[i]); } if (log.IsInfoEnabled) { log.Info("Modified " + count + " bytes."); log.Info(buffer.GetHexDump()); } } }
/// <inheritdoc/> public override void MessageReceived(INextFilter nextFilter, IoSession session, Object message) { //if (log.IsDebugEnabled) // log.DebugFormat("Processing a MESSAGE_RECEIVED for session {0}", session.Id); IoBuffer input = message as IoBuffer; if (input == null) { nextFilter.MessageReceived(session, message); return; } IProtocolDecoder decoder = _factory.GetDecoder(session); IProtocolDecoderOutput decoderOutput = GetDecoderOut(session, nextFilter); // Loop until we don't have anymore byte in the buffer, // or until the decoder throws an unrecoverable exception or // can't decoder a message, because there are not enough // data in the buffer while (input.HasRemaining) { Int32 oldPos = input.Position; try { // TODO may not need lock on UDP lock (session) { // Call the decoder with the read bytes decoder.Decode(session, input, decoderOutput); } // Finish decoding if no exception was thrown. decoderOutput.Flush(nextFilter, session); } catch (Exception ex) { ProtocolDecoderException pde = ex as ProtocolDecoderException; if (pde == null) { pde = new ProtocolDecoderException(null, ex); } if (pde.Hexdump == null) { // Generate a message hex dump Int32 curPos = input.Position; input.Position = oldPos; pde.Hexdump = input.GetHexDump(); input.Position = curPos; } decoderOutput.Flush(nextFilter, session); nextFilter.ExceptionCaught(session, pde); // Retry only if the type of the caught exception is // recoverable and the buffer position has changed. // We check buffer position additionally to prevent an // infinite loop. if (!(ex is RecoverableProtocolDecoderException) || input.Position == oldPos) { break; } } } }
/// <inheritdoc/> protected override bool DoDecode(IoSession session, IoBuffer input, IProtocolDecoderOutput output) { State state = GetState(session); if (state.currentDecoder == null) { IMessageDecoder[] decoders = state.decoders; int undecodables = 0; for (int i = decoders.Length - 1; i >= 0; i--) { IMessageDecoder decoder = decoders[i]; int limit = input.Limit; int pos = input.Position; MessageDecoderResult result; try { result = decoder.Decodable(session, input); } finally { input.Position = pos; input.Limit = limit; } if (result == MessageDecoderResult.OK) { state.currentDecoder = decoder; break; } else if (result == MessageDecoderResult.NotOK) { undecodables++; } else if (result != MessageDecoderResult.NeedData) { throw new InvalidOperationException("Unexpected decode result (see your decodable()): " + result); } } if (undecodables == decoders.Length) { // Throw an exception if all decoders cannot decode data. String dump = input.GetHexDump(); input.Position = input.Limit; // Skip data //seem to be a bug not remove session buffer //add code to remove session buffer. RemoveSessionBuffer(session); ProtocolDecoderException e = new ProtocolDecoderException("No appropriate message decoder: " + dump); e.Hexdump = dump; throw e; } if (state.currentDecoder == null) { // Decoder is not determined yet (i.e. we need more data) return(false); } } try { MessageDecoderResult result = state.currentDecoder.Decode(session, input, output); if (result == MessageDecoderResult.OK) { state.currentDecoder = null; return(true); } else if (result == MessageDecoderResult.NeedData) { return(false); } else if (result == MessageDecoderResult.NotOK) { state.currentDecoder = null; throw new ProtocolDecoderException("Message decoder returned NOT_OK."); } else { state.currentDecoder = null; throw new InvalidOperationException("Unexpected decode result (see your decode()): " + result); } } catch (Exception) { state.currentDecoder = null; throw; } }