TcpSession *ssn, TcpStream *stream, TcpSegment *seg, ReassembleData *rd,
Packet *p)
{
+ /* fast path 1: segment is exactly what we need */
+ if (likely(rd->data_len == 0 && SEQ_EQ(seg->seq, rd->ra_base_seq+1) && SEQ_EQ(stream->last_ack, (seg->seq + seg->payload_len)))) {
+ /* process single segment directly */
+ AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream,
+ seg->payload, seg->payload_len,
+ StreamGetAppLayerFlags(ssn, stream, p));
+ AppLayerProfilingStore(ra_ctx->app_tctx, p);
+ rd->data_sent += seg->payload_len;
+ rd->ra_base_seq += seg->payload_len;
+
+ /* if after the first data chunk we have no alproto yet,
+ * there is no point in continueing here. */
+ if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)) {
+ SCLogDebug("no alproto after first data chunk");
+ return 0;
+ }
+ return 1;
+ /* fast path 2: segment acked completely, meets minimal size req for 0copy processing */
+ } else if (rd->data_len == 0 && SEQ_EQ(seg->seq, rd->ra_base_seq+1) && SEQ_GT(stream->last_ack, (seg->seq + seg->payload_len)) && seg->payload_len >= 128) {
+ /* process single segment directly */
+ AppLayerHandleTCPData(tv, ra_ctx, p, p->flow, ssn, stream,
+ seg->payload, seg->payload_len,
+ StreamGetAppLayerFlags(ssn, stream, p));
+ AppLayerProfilingStore(ra_ctx->app_tctx, p);
+ rd->data_sent += seg->payload_len;
+ rd->ra_base_seq += seg->payload_len;
+
+ /* if after the first data chunk we have no alproto yet,
+ * there is no point in continueing here. */
+ if (!StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)) {
+ SCLogDebug("no alproto after first data chunk");
+ return 0;
+ }
+ return 1;
+ }
+
uint16_t payload_offset = 0;
uint16_t payload_len = 0;