]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
App layer protocol detection updated and improved. We now use
authorAnoop Saldanha <anoopsaldanha@gmail.com>
Sun, 4 Aug 2013 06:38:59 +0000 (12:08 +0530)
committerAnoop Saldanha <anoopsaldanha@gmail.com>
Sun, 29 Sep 2013 17:43:08 +0000 (23:13 +0530)
confirmation from both directions and set events if there's a mismatch
between the 2 directions.

FPs from corrupt flows have disappeared with this.

22 files changed:
src/app-layer-dcerpc-udp.c
src/app-layer-dcerpc.c
src/app-layer-detect-proto.c
src/app-layer-ftp.c
src/app-layer-htp.c
src/app-layer-parser.c
src/app-layer-parser.h
src/app-layer-smb.c
src/app-layer-smb2.c
src/app-layer-smtp.c
src/app-layer-ssh.c
src/app-layer-ssl.c
src/app-layer.c
src/app-layer.h
src/flow-util.h
src/flow.h
src/runmode-unittests.c
src/stream-tcp-private.h
src/stream-tcp-reassemble.c
src/stream-tcp-reassemble.h
src/stream-tcp.c
src/stream-tcp.h

index 68b343da20c4f78e316b945431563033ae414bd7..53a2cbf442f23e7a45ec1752583b604cab2b851a 100644 (file)
@@ -722,6 +722,7 @@ void RegisterDCERPCUDPParsers(void) {
 
     if (AppLayerProtoDetectionEnabled("dcerpc")) {
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_UDP, ALPROTO_DCERPC_UDP, "|04 00|", 2, 0, STREAM_TOSERVER);
+        AppLayerRegisterParserAcceptableDataDirection(ALPROTO_DCERPC_UDP, STREAM_TOSERVER);
     } else {
         SCLogInfo("Protocol detection and parser disabled for %s protocol.",
                   "dcerpc");
@@ -740,7 +741,7 @@ void RegisterDCERPCUDPParsers(void) {
                   "still on.", "dcerpc");
     }
 #ifdef UNITTESTS
-    AppLayerRegisterUnittests(ALPROTO_DCERPC_UDP, DCERPCUDPParserRegisterTests);
+    AppLayerParserRegisterUnittests(ALPROTO_DCERPC_UDP, DCERPCUDPParserRegisterTests);
 #endif
 
     return;
index 37a12f61e16b8afa8e3ff11596ab22ae5b5bb9f8..c9bb21121846b3dfc3a7ffe125693a09732e2eb4 100644 (file)
@@ -1871,6 +1871,9 @@ void RegisterDCERPCParsers(void) {
 
     if (AppLayerProtoDetectionEnabled(proto_name)) {
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0, STREAM_TOSERVER);
+        /* toclient direction */
+        AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_DCERPC, "|05 00|", 2, 0, STREAM_TOCLIENT);
+        AppLayerRegisterParserAcceptableDataDirection(ALPROTO_DCERPC, STREAM_TOSERVER);
     } else {
         SCLogInfo("Protocol detection and parser disabled for %s protocol.",
                   proto_name);
@@ -1889,7 +1892,7 @@ void RegisterDCERPCParsers(void) {
                   "still on.", proto_name);
     }
 #ifdef UNITTESTS
-    AppLayerRegisterUnittests(ALPROTO_DCERPC, DCERPCParserRegisterTests);
+    AppLayerParserRegisterUnittests(ALPROTO_DCERPC, DCERPCParserRegisterTests);
 #endif
 
     return;
index 1cff7053c0215577c5c3d6afee541cf26538bafd..7e911ccaf802c29adcf76fe2f22c087163bf616a 100644 (file)
@@ -573,8 +573,17 @@ uint16_t AppLayerDetectGetProto(AlpProtoDetectCtx *ctx,
 {
     if (!FLOW_IS_PM_DONE(f, flags)) {
         uint16_t pm_results[ALPROTO_MAX];
-        if (AppLayerDetectGetProtoPMParser(ctx, tctx, f, buf, buflen, flags, ipproto, pm_results) != 0) {
-            return pm_results[0];
+        uint16_t pm_matches = AppLayerDetectGetProtoPMParser(ctx, tctx, f, buf, buflen, flags, ipproto, pm_results);
+        uint8_t dir = (flags & STREAM_TOSERVER) ? 0 : 1;
+        for (uint16_t i = 0; i < pm_matches; i++) {
+            if (al_proto_table[pm_results[i]].pp_alproto_map[dir] != NULL) {
+                if (pm_results[i] != al_proto_table[pm_results[i]].pp_alproto_map[dir](buf, buflen, NULL)) {
+                    /* \todo set event */
+                    continue;
+                }
+            }
+
+            return pm_results[i];
         }
     }
     if (!FLOW_IS_PP_DONE(f, flags))
index 6930a9c4f877f9c5e3bf74d7adfadf98fb83e6a1..7cb19ff6ec9475a8f8fe75755f599b2b11534129 100644 (file)
@@ -270,6 +270,7 @@ void RegisterFTPParsers(void) {
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_FTP, "USER ", 5, 0, STREAM_TOSERVER);
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_FTP, "PASS ", 5, 0, STREAM_TOSERVER);
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_FTP, "PORT ", 5, 0, STREAM_TOSERVER);
+        AppLayerRegisterParserAcceptableDataDirection(ALPROTO_FTP, STREAM_TOSERVER | STREAM_TOCLIENT);
     }
 
     if (AppLayerParserEnabled(proto_name)) {
@@ -286,7 +287,7 @@ void RegisterFTPParsers(void) {
                   "still on.", proto_name);
     }
 #ifdef UNITTESTS
-    AppLayerRegisterUnittests(ALPROTO_FTP, FTPParserRegisterTests);
+    AppLayerParserRegisterUnittests(ALPROTO_FTP, FTPParserRegisterTests);
 #endif
 }
 
index 2fb6987fcdc7c97a118638e25fcb2f25c7f395b4..d556893dfdd5f59f82a8b28cc50de1aa1d7c6ecc 100644 (file)
@@ -2420,6 +2420,12 @@ void RegisterHTPParsers(void)
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "OPTIONS|09|", 8, 0, STREAM_TOSERVER);
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "CONNECT|20|", 8, 0, STREAM_TOSERVER);
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "CONNECT|09|", 8, 0, STREAM_TOSERVER);
+
+        /* toclient direction */
+        AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "HTTP/0.9", 8, 0, STREAM_TOCLIENT);
+        AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "HTTP/1.0", 8, 0, STREAM_TOCLIENT);
+        AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_HTTP, "HTTP/1.1", 8, 0, STREAM_TOCLIENT);
+        AppLayerRegisterParserAcceptableDataDirection(ALPROTO_HTTP, STREAM_TOSERVER);
     } else {
         SCLogInfo("Protocol detection and parser disabled for %s protocol",
                   proto_name);
@@ -2451,7 +2457,7 @@ void RegisterHTPParsers(void)
                   "still on.", proto_name);
     }
 #ifdef UNITTESTS
-    AppLayerRegisterUnittests(ALPROTO_HTTP, HTPParserRegisterTests);
+    AppLayerParserRegisterUnittests(ALPROTO_HTTP, HTPParserRegisterTests);
 #endif
 
     SCReturn;
index 12c5e774fd8a6c7e2cea8ce8373a3237188b5b46..fe9b3a40afdd6ed37820452c8c7ab55e29e48545 100644 (file)
@@ -758,7 +758,7 @@ int AppLayerRegisterProto(char *name, uint8_t proto, uint8_t flags,
 }
 
 #ifdef UNITTESTS
-void AppLayerRegisterUnittests(uint16_t proto, void (*RegisterUnittests)(void)) {
+void AppLayerParserRegisterUnittests(uint16_t proto, void (*RegisterUnittests)(void)) {
     al_proto_table[proto].RegisterUnittests = RegisterUnittests;
 }
 #endif
@@ -2240,6 +2240,23 @@ static inline void AppLayerInsertNewProbingParser(AppLayerProbingParser **pp,
     return;
 }
 
+void AppLayerRegisterParserAcceptableDataDirection(uint16_t al_proto,
+                                                   uint8_t flags)
+{
+    al_proto_table[al_proto].flags |= (flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
+
+    return;
+}
+
+void AppLayerMapProbingParserAgainstAlproto(uint16_t al_proto,
+                                            uint8_t flags,
+                                            ProbingParserFPtr ProbingParser)
+{
+    al_proto_table[al_proto].pp_alproto_map[(flags & STREAM_TOSERVER) ? 0 : 1] = ProbingParser;
+
+    return;
+}
+
 void AppLayerRegisterProbingParser(AlpProtoDetectCtx *ctx,
                                    uint16_t ip_proto,
                                    char *portstr,
index a2dccfefa3608b766464c2df224b7abaf1744c8d..ba016e94987cb1b0928b970c22009f708a9fee0f 100644 (file)
@@ -34,6 +34,9 @@ typedef struct AppLayerLocalMap_ {
     uint16_t parser_id;
 } AppLayerLocalMap;
 
+typedef uint16_t (*ProbingParserFPtr)(uint8_t *input, uint32_t input_len,
+                                      uint32_t *offset);
+
 /** \brief Mapping between ALPROTO_* and L7Parsers
  *
  * Map the proto to the parsers for the to_client and to_server directions.
@@ -66,6 +69,10 @@ typedef struct AppLayerProto_ {
     void *(*StateGetTx)(void *alstate, uint64_t tx_id);
     int (*StateGetAlstateProgressCompletionStatus)(uint8_t direction);
 
+    ProbingParserFPtr pp_alproto_map[2];
+    /* The current values taken are STREAM_TOSERVER, STREAM_TOCLIENT */
+    uint8_t flags;
+
 #ifdef UNITTESTS
     void (*RegisterUnittests)(void);
 #endif
@@ -138,9 +145,6 @@ typedef struct AppLayerParserStateStore_ {
     AppLayerDecoderEvents *decoder_events;
 } AppLayerParserStateStore;
 
-typedef uint16_t (*ProbingParserFPtr)(uint8_t *input, uint32_t input_len,
-                                      uint32_t *offset);
-
 typedef struct AppLayerParserTableElement_ {
     int (*AppLayerParser)(Flow *f, void *protocol_state, AppLayerParserState
                           *parser_state, uint8_t *input, uint32_t input_len,
@@ -242,6 +246,11 @@ int AppLayerRegisterParser(char *name, uint16_t proto, uint16_t parser_id,
                                                  void *local_data,
                                                  AppLayerParserResult *output),
                            char *dependency);
+void AppLayerRegisterParserAcceptableDataDirection(uint16_t al_proto,
+                                                   uint8_t flags);
+void AppLayerMapProbingParserAgainstAlproto(uint16_t al_proto,
+                                            uint8_t flags,
+                                            ProbingParserFPtr ProbingParser);
 void AppLayerRegisterProbingParser(struct AlpProtoDetectCtx_ *,
                                    uint16_t ip_proto,
                                    char *portstr,
@@ -250,7 +259,7 @@ void AppLayerRegisterProbingParser(struct AlpProtoDetectCtx_ *,
                                    uint8_t flags,
                                    ProbingParserFPtr ProbingParser);
 #ifdef UNITTESTS
-void AppLayerRegisterUnittests(uint16_t proto, void (*RegisterUnittests)(void));
+void AppLayerParserRegisterUnittests(uint16_t proto, void (*RegisterUnittests)(void));
 #endif
 void AppLayerRegisterStateFuncs(uint16_t proto, void *(*StateAlloc)(void),
                                 void (*StateFree)(void *));
index 7b9989ab7caf067b92bfda2e708b542c97d40be5..fa4740d8dd7774091e4b61b06d8f6cddfa3b2f04 100644 (file)
@@ -1420,6 +1420,8 @@ void RegisterSMBParsers(void) {
                                             SMB_PROBING_PARSER_MIN_DEPTH, 0,
                                             SMBProbingParser);
         }
+
+        AppLayerRegisterParserAcceptableDataDirection(ALPROTO_SMB, STREAM_TOSERVER);
     } else {
         SCLogInfo("Protocol detection and parser disabled for %s protocol.",
                   proto_name);
@@ -1436,7 +1438,7 @@ void RegisterSMBParsers(void) {
     }
 
 #ifdef UNITTESTS
-    AppLayerRegisterUnittests(ALPROTO_SMB, SMBParserRegisterTests);
+    AppLayerParserRegisterUnittests(ALPROTO_SMB, SMBParserRegisterTests);
 #endif
     return;
 }
index 1b303bfd491f90acefb54f172c548f501e20a0d7..81f5f5c5e7b732797cc6b64264115c1bd0fafa25 100644 (file)
@@ -531,7 +531,7 @@ void RegisterSMB2Parsers(void) {
     }
 
 #ifdef UNITTESTS
-    AppLayerRegisterUnittests(ALPROTO_SMB2, SMB2ParserRegisterTests);
+    AppLayerParserRegisterUnittests(ALPROTO_SMB2, SMB2ParserRegisterTests);
 #endif
     return;
 }
index 6d54bfca23bfeb8eb49dd3dc6ba1a07b0c7f5cdd..81ac8ee051070050b93f5e25acd2896021010bf3 100644 (file)
@@ -532,26 +532,16 @@ static int SMTPProcessReply(SMTPState *state, Flow *f,
     reply_code = smtp_reply_map[pmq->pattern_id_array[0]].enum_value;
 
     if (state->cmds_idx == state->cmds_cnt) {
-        /* decoder event - unable to match reply with request */
-        SCLogDebug("unable to match reply with request");
-        SCReturnInt(-1);
-    }
-
-    /* kinda hack needed for us.  Our parser logs commands, to be
-     * matched against server replies.  SMTP is normally accompanied by a
-     * toclient welcome message, which would have had no command to
-     * accompany it with.  And also alproto detection sees to it that the
-     * toserver stream is the first one to be processed by the app layer.
-     * Hence check the first reply and if it is a welcome message(220),
-     * leave without matching it against any buffered command */
-    if (!(state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
-        state->parser_state |= SMTP_PARSER_STATE_FIRST_REPLY_SEEN;
-        if (reply_code == SMTP_REPLY_220) {
-            return 0;
+        if (!(state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
+            state->parser_state |= SMTP_PARSER_STATE_FIRST_REPLY_SEEN;
+            if (reply_code == SMTP_REPLY_220)
+                SCReturnInt(0);
+            else
+                AppLayerDecoderEventsSetEvent(f, SMTP_DECODER_EVENT_INVALID_REPLY);
         } else {
-            /* set decoder event - first reply from server not a welcome message */
-            AppLayerDecoderEventsSetEvent(f,
-                                          SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE);
+            /* decoder event - unable to match reply with request */
+            SCLogDebug("unable to match reply with request");
+            SCReturnInt(-1);
         }
     }
 
@@ -633,6 +623,10 @@ static int SMTPProcessRequest(SMTPState *state, Flow *f,
 {
     SCEnter();
 
+    if (!(state->parser_state & SMTP_PARSER_STATE_FIRST_REPLY_SEEN)) {
+        AppLayerDecoderEventsSetEvent(f, SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE);
+    }
+
     /* there are 2 commands that can push it into this COMMAND_DATA mode -
      * STARTTLS and DATA */
     if (!(state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
@@ -852,6 +846,9 @@ void RegisterSMTPParsers(void)
                     STREAM_TOSERVER);
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_SMTP, "HELO", 4, 0,
                     STREAM_TOSERVER);
+        AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_SMTP, "QUIT", 4, 0,
+                STREAM_TOSERVER);
+        AppLayerRegisterParserAcceptableDataDirection(ALPROTO_SMTP, STREAM_TOCLIENT);
     } else {
         SCLogInfo("Protocol detection and parser disabled for %s protocol.",
                   proto_name);
@@ -877,7 +874,7 @@ void RegisterSMTPParsers(void)
     SMTPSetMpmState();
 
 #ifdef UNITTESTS
-    AppLayerRegisterUnittests(ALPROTO_SMTP, SMTPParserRegisterTests);
+    AppLayerParserRegisterUnittests(ALPROTO_SMTP, SMTPParserRegisterTests);
 #endif
     return;
 }
@@ -966,8 +963,8 @@ int SMTPParserTest01(void)
     void *thread_local_data = SMTPLocalStorageAlloc();
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
-                      request1, request1_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
+                      welcome_reply, welcome_reply_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
@@ -980,17 +977,16 @@ int SMTPParserTest01(void)
         goto end;
     }
     if (smtp_state->input_len != 0 ||
-        smtp_state->cmds_cnt != 1 ||
+        smtp_state->cmds_cnt != 0 ||
         smtp_state->cmds_idx != 0 ||
-        smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
-        smtp_state->parser_state != 0) {
+        smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
         printf("smtp parser in inconsistent state\n");
         goto end;
     }
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
-                      welcome_reply, welcome_reply_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
+                      request1, request1_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
@@ -1323,8 +1319,8 @@ int SMTPParserTest02(void)
     void *thread_local_data = SMTPLocalStorageAlloc();
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
-                      request1, request1_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
+                      welcome_reply, welcome_reply_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
@@ -1337,17 +1333,16 @@ int SMTPParserTest02(void)
         goto end;
     }
     if (smtp_state->input_len != 0 ||
-        smtp_state->cmds_cnt != 1 ||
+        smtp_state->cmds_cnt != 0 ||
         smtp_state->cmds_idx != 0 ||
-        smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
-        smtp_state->parser_state != 0) {
+        smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
         printf("smtp parser in inconsistent state\n");
         goto end;
     }
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
-                      welcome_reply, welcome_reply_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
+                      request1, request1_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
@@ -1956,8 +1951,8 @@ int SMTPParserTest03(void)
     void *thread_local_data = SMTPLocalStorageAlloc();
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
-                      request1, request1_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
+                      welcome_reply, welcome_reply_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
@@ -1970,17 +1965,16 @@ int SMTPParserTest03(void)
         goto end;
     }
     if (smtp_state->input_len != 0 ||
-        smtp_state->cmds_cnt != 1 ||
+        smtp_state->cmds_cnt != 0 ||
         smtp_state->cmds_idx != 0 ||
-        smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
-        smtp_state->parser_state != 0) {
+        smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
         printf("smtp parser in inconsistent state\n");
         goto end;
     }
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
-                      welcome_reply, welcome_reply_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
+                      request1, request1_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
@@ -2102,8 +2096,8 @@ int SMTPParserTest04(void)
     void *thread_local_data = SMTPLocalStorageAlloc();
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
-                      request1, request1_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
+                      welcome_reply, welcome_reply_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
@@ -2116,17 +2110,16 @@ int SMTPParserTest04(void)
         goto end;
     }
     if (smtp_state->input_len != 0 ||
-        smtp_state->cmds_cnt != 1 ||
+        smtp_state->cmds_cnt != 0 ||
         smtp_state->cmds_idx != 0 ||
-        smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
-        smtp_state->parser_state != 0) {
+        smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
         printf("smtp parser in inconsistent state\n");
         goto end;
     }
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
-                      welcome_reply, welcome_reply_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
+                      request1, request1_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
@@ -2248,8 +2241,8 @@ int SMTPParserTest05(void)
     void *thread_local_data = SMTPLocalStorageAlloc();
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
-                      request1, request1_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
+                      welcome_reply, welcome_reply_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
@@ -2262,17 +2255,16 @@ int SMTPParserTest05(void)
         goto end;
     }
     if (smtp_state->input_len != 0 ||
-        smtp_state->cmds_cnt != 1 ||
+        smtp_state->cmds_cnt != 0 ||
         smtp_state->cmds_idx != 0 ||
-        smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
-        smtp_state->parser_state != 0) {
+        smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
         printf("smtp parser in inconsistent state\n");
         goto end;
     }
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
-                      welcome_reply, welcome_reply_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
+                      request1, request1_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
@@ -2543,8 +2535,8 @@ int SMTPParserTest06(void)
     void *thread_local_data = SMTPLocalStorageAlloc();
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
-                      request1, request1_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
+                      welcome_reply, welcome_reply_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
@@ -2557,17 +2549,16 @@ int SMTPParserTest06(void)
         goto end;
     }
     if (smtp_state->input_len != 0 ||
-        smtp_state->cmds_cnt != 1 ||
+        smtp_state->cmds_cnt != 0 ||
         smtp_state->cmds_idx != 0 ||
-        smtp_state->cmds[0] != SMTP_COMMAND_OTHER_CMD ||
-        smtp_state->parser_state != 0) {
+        smtp_state->parser_state != SMTP_PARSER_STATE_FIRST_REPLY_SEEN) {
         printf("smtp parser in inconsistent state\n");
         goto end;
     }
 
     SCMutexLock(&f.m);
-    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOCLIENT,
-                      welcome_reply, welcome_reply_len);
+    r = AppLayerParse(thread_local_data, &f, ALPROTO_SMTP, STREAM_TOSERVER,
+                      request1, request1_len);
     if (r != 0) {
         printf("smtp check returned %" PRId32 ", expected 0: ", r);
         SCMutexUnlock(&f.m);
index 700b280facad7e19cc179dfbb3425e8d36bac88d..c915af5adf23362586eebc3418f44ac27c72bf43 100644 (file)
@@ -741,6 +741,7 @@ void RegisterSSHParsers(void)
     /** SSH */
     if (AppLayerProtoDetectionEnabled(proto_name)) {
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_SSH, "SSH-", 4, 0, STREAM_TOSERVER);
+        AppLayerRegisterParserAcceptableDataDirection(ALPROTO_SSH, STREAM_TOSERVER | STREAM_TOCLIENT);
     } else {
         SCLogInfo("Protocol detection and parser disabled for %s protocol.",
                   proto_name);
@@ -759,7 +760,7 @@ void RegisterSSHParsers(void)
     }
 
 #ifdef UNITTESTS
-    AppLayerRegisterUnittests(ALPROTO_SSH, SSHParserRegisterTests);
+    AppLayerParserRegisterUnittests(ALPROTO_SSH, SSHParserRegisterTests);
 #endif
 }
 
index 0a782611f221756233d7d34aeac61851edbb1239..cd1a1bdfcdeed89cb033059e75c1879c513588ee 100644 (file)
@@ -1016,6 +1016,15 @@ void RegisterSSLParsers(void)
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|01 03 03|", 3, 0, STREAM_TOSERVER);
         AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|16 03 03|", 3, 0, STREAM_TOSERVER); /* client hello */
 
+        /* toclient direction */
+        AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|16 03 00|", 3, 0, STREAM_TOCLIENT); /* server hello */
+        /** TLSv1 */
+        AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|16 03 01|", 3, 0, STREAM_TOCLIENT); /* server hello */
+        /** TLSv1.1 */
+        AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|16 03 02|", 3, 0, STREAM_TOCLIENT); /* server hello */
+        /** TLSv1.2 */
+        AlpProtoAdd(&alp_proto_ctx, proto_name, IPPROTO_TCP, ALPROTO_TLS, "|16 03 03|", 3, 0, STREAM_TOCLIENT); /* server hello */
+
         if (RunmodeIsUnittests()) {
             AppLayerRegisterProbingParser(&alp_proto_ctx,
                                           IPPROTO_TCP,
@@ -1030,6 +1039,8 @@ void RegisterSSLParsers(void)
                                             0, 3,
                                             SSLProbingParser);
         }
+
+        AppLayerRegisterParserAcceptableDataDirection(ALPROTO_TLS, STREAM_TOSERVER);
     } else {
         SCLogInfo("Protocol detection and parser disabled for %s protocol",
                   proto_name);
@@ -1060,7 +1071,7 @@ void RegisterSSLParsers(void)
     }
 
 #ifdef UNITTESTS
-    AppLayerRegisterUnittests(ALPROTO_TLS, SSLParserRegisterTests);
+    AppLayerParserRegisterUnittests(ALPROTO_TLS, SSLParserRegisterTests);
 #endif
 
     /* Get the value of no reassembly option from the config file */
index d77b9b24d86f73e0bbe6828d398e9e5ecd87514e..6f950e2732b939ceea8c3221f0f392a74f9ee889 100644 (file)
@@ -113,12 +113,13 @@ extern AlpProtoDetectCtx alp_proto_ctx;
  *  \retval 0 ok
  *  \retval -1 error
  */
-int AppLayerHandleTCPData(AlpProtoDetectThreadCtx *dp_ctx, Flow *f,
-                          TcpSession *ssn, TcpStream *stream,
-                          uint8_t *data, uint32_t data_len,
+int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
+                          Flow *f, TcpSession *ssn, TcpStream *stream,
+                          uint8_t *data, uint32_t data_len, Packet *p,
                           uint8_t flags)
 {
     SCEnter();
+    AlpProtoDetectThreadCtx *dp_ctx = &ra_ctx->dp_ctx;
 
     DEBUG_ASSERT_FLOW_LOCKED(f);
 
@@ -135,17 +136,34 @@ int AppLayerHandleTCPData(AlpProtoDetectThreadCtx *dp_ctx, Flow *f,
         SCReturnInt(r);
     }
 
+    uint16_t *alproto;
+    uint16_t *alproto_otherdir;
+    uint8_t dir;
+    if (flags & STREAM_TOSERVER) {
+        alproto = &f->alproto_ts;
+        alproto_otherdir = &f->alproto_tc;
+        dir = 0;
+    } else {
+        alproto = &f->alproto_tc;
+        alproto_otherdir = &f->alproto_ts;
+        dir = 1;
+    }
+
     /* if we don't know the proto yet and we have received a stream
      * initializer message, we run proto detection.
      * We receive 2 stream init msgs (one for each direction) but we
      * only run the proto detection once. */
-    if (f->alproto == ALPROTO_UNKNOWN && (flags & STREAM_GAP)) {
-        //stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
-        ssn->client.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
-        ssn->server.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
+    if (*alproto == ALPROTO_UNKNOWN && (flags & STREAM_GAP)) {
+        stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
         SCLogDebug("ALPROTO_UNKNOWN flow %p, due to GAP in stream start", f);
-        StreamTcpSetSessionNoReassemblyFlag(ssn, 0);
-    } else if (f->alproto == ALPROTO_UNKNOWN && (flags & STREAM_START)) {
+        StreamTcpSetSessionNoReassemblyFlag(ssn, dir);
+    } else if (*alproto == ALPROTO_UNKNOWN && (flags & STREAM_START)) {
+        uint32_t data_al_so_far;
+        if (data_len == 0)
+            data_al_so_far = 0;
+        else
+            data_al_so_far = f->data_al_so_far[dir];
+
         SCLogDebug("Stream initializer (len %" PRIu32 ")", data_len);
 #ifdef PRINT
         if (data_len > 0) {
@@ -158,25 +176,91 @@ int AppLayerHandleTCPData(AlpProtoDetectThreadCtx *dp_ctx, Flow *f,
 #endif
 
         PACKET_PROFILING_APP_PD_START(dp_ctx);
-        f->alproto = AppLayerDetectGetProto(&alp_proto_ctx, dp_ctx, f,
-                                            data, data_len, flags, IPPROTO_TCP);
+        *alproto = AppLayerDetectGetProto(&alp_proto_ctx, dp_ctx, f,
+                                          data, data_len, flags, IPPROTO_TCP);
         PACKET_PROFILING_APP_PD_END(dp_ctx);
 
-        if (f->alproto != ALPROTO_UNKNOWN) {
-            //stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
-            ssn->client.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
-            ssn->server.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
-
-            PACKET_PROFILING_APP_START(dp_ctx, f->alproto);
-            r = AppLayerParse(dp_ctx->alproto_local_storage[f->alproto], f, f->alproto, flags, data, data_len);
-            PACKET_PROFILING_APP_END(dp_ctx, f->alproto);
-        } else {
-            if ((FLOW_IS_PM_DONE(f, STREAM_TOSERVER)) && (FLOW_IS_PM_DONE(f, STREAM_TOCLIENT)) &&
-                (FLOW_IS_PP_DONE(f, STREAM_TOSERVER)) && (FLOW_IS_PP_DONE(f, STREAM_TOCLIENT))) {
+        if (*alproto != ALPROTO_UNKNOWN) {
+            if (*alproto_otherdir != ALPROTO_UNKNOWN && *alproto_otherdir != *alproto) {
+                /* \todo set event */
+                f->alproto = f->alproto_ts = f->alproto_tc = ALPROTO_UNKNOWN;
                 FlowSetSessionNoApplayerInspectionFlag(f);
-                //stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
                 ssn->client.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
                 ssn->server.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
+            } else {
+                f->alproto = *alproto;
+                stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
+
+                if ((ssn->data_first_seen_dir & (STREAM_TOSERVER | STREAM_TOCLIENT)) &&
+                    !(flags & ssn->data_first_seen_dir)) {
+                    TcpStream *opposing_stream = NULL;
+                    if (stream == &ssn->client) {
+                        opposing_stream = &ssn->server;
+                        p->flowflags &= ~FLOW_PKT_TOCLIENT;
+                        p->flowflags |= FLOW_PKT_TOSERVER;
+                    } else {
+                        opposing_stream = &ssn->client;
+                        p->flowflags &= ~FLOW_PKT_TOSERVER;
+                        p->flowflags |= FLOW_PKT_TOCLIENT;
+                    }
+
+                    int ret = StreamTcpReassembleAppLayer(tv, ra_ctx, ssn, opposing_stream, p);
+                    if (stream == &ssn->client) {
+                        p->flowflags &= ~FLOW_PKT_TOSERVER;
+                        p->flowflags |= FLOW_PKT_TOCLIENT;
+                    } else {
+                        p->flowflags &= ~FLOW_PKT_TOCLIENT;
+                        p->flowflags |= FLOW_PKT_TOSERVER;
+                    }
+                    if (ret < 0) {
+                        r = -1;
+                        goto end;
+                    }
+                }
+
+                if (ssn->data_first_seen_dir != 0x01) {
+                    if (al_proto_table[*alproto].flags && !(al_proto_table[*alproto].flags & ssn->data_first_seen_dir)) {
+                        /* \todo Set event */
+                        r = -1;
+                        f->alproto = f->alproto_ts = f->alproto_tc = ALPROTO_UNKNOWN;
+                        FlowSetSessionNoApplayerInspectionFlag(f);
+                        ssn->server.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
+                        ssn->client.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
+                        /* Set a value that is neither STREAM_TOSERVER, nor STREAM_TOCLIENT */
+                        ssn->data_first_seen_dir = 0x01;
+                        goto end;
+                    }
+                }
+
+                /* Set a value that is neither STREAM_TOSERVER, nor STREAM_TOCLIENT */
+                ssn->data_first_seen_dir = 0x01;
+
+                PACKET_PROFILING_APP_START(dp_ctx, *alproto);
+                r = AppLayerParse(dp_ctx->alproto_local_storage[*alproto], f, *alproto, flags, data + data_al_so_far, data_len - data_al_so_far);
+                PACKET_PROFILING_APP_END(dp_ctx, *alproto);
+                f->data_al_so_far[dir] = 0;
+            }
+        } else {
+            if (*alproto_otherdir != ALPROTO_UNKNOWN) {
+                PACKET_PROFILING_APP_START(dp_ctx, *alproto_otherdir);
+                r = AppLayerParse(dp_ctx->alproto_local_storage[*alproto_otherdir], f, *alproto_otherdir, flags,
+                                  data + data_al_so_far, data_len - data_al_so_far);
+                PACKET_PROFILING_APP_END(dp_ctx, *alproto_otherdir);
+                if (FLOW_IS_PM_DONE(f, flags) && FLOW_IS_PP_DONE(f, flags)) {
+                    /* \todo event.  Unable to detect protocol for one direction */
+                    stream->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
+                    f->data_al_so_far[dir] = 0;
+                } else {
+                    f->data_al_so_far[dir] = data_len;
+                }
+            } else {
+                if (FLOW_IS_PM_DONE(f, STREAM_TOSERVER) && FLOW_IS_PP_DONE(f, STREAM_TOSERVER) &&
+                    FLOW_IS_PM_DONE(f, STREAM_TOCLIENT) && FLOW_IS_PP_DONE(f, STREAM_TOCLIENT)) {
+                    ssn->client.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
+                    ssn->server.flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED;
+                    ssn->data_first_seen_dir = 0x01;
+                    FlowSetSessionNoApplayerInspectionFlag(f);
+                }
             }
         }
     } else {
@@ -202,6 +286,7 @@ int AppLayerHandleTCPData(AlpProtoDetectThreadCtx *dp_ctx, Flow *f,
         }
     }
 
+ end:
     SCReturnInt(r);
 }
 
@@ -360,3 +445,2849 @@ int AppLayerHandleUdp(AlpProtoDetectThreadCtx *dp_ctx, Flow *f, Packet *p)
     SCReturnInt(r);
 }
 
+/************Unittests*************/
+
+#ifdef UNITTESTS
+
+#include "stream-tcp.h"
+#include "stream-tcp-private.h"
+#include "stream-tcp-reassemble.h"
+#include "stream-tcp-inline.h"
+#include "stream-tcp-util.h"
+#include "stream.h"
+#include "util-unittest.h"
+
+/**
+ * \test GET -> HTTP/1.1
+ */
+static int AppLayerTest01(void)
+{
+    Packet *p = SCMalloc(SIZE_OF_PACKET);
+    if (unlikely(p == NULL))
+        return 0;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
+    TCPHdr tcph;
+    PacketQueue pq;
+    memset(&pq,0,sizeof(PacketQueue));
+    memset(p, 0, SIZE_OF_PACKET);
+    memset (&f, 0, sizeof(Flow));
+    memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
+
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
+    p->tcph = &tcph;
+
+    int ret = 0;
+
+    StreamTcpInitConfig(TRUE);
+
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+
+    TcpSession *ssn = (TcpSession *)f.protoctx;
+
+    /* handshake */
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
+        goto end;
+    }
+
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* full request */
+    uint8_t request[] = {
+        0x47, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
+        0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
+        0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
+        0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
+        0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
+        0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
+        0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
+        0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
+        0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
+        0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request);
+    p->payload = request;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+    /* full response - request ack */
+    uint8_t response[] = {
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(88);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response);
+    p->payload = response;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    /* response ack */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(88);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 6\n");
+        goto end;
+    }
+
+    StreamTcpSessionClear(p->flow->protoctx);
+
+    ret = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    SCFree(p);
+    return ret;
+}
+
+/**
+ * \test GE -> T -> HTTP/1.1
+ */
+static int AppLayerTest02(void)
+{
+    Packet *p = SCMalloc(SIZE_OF_PACKET);
+    if (unlikely(p == NULL))
+        return 0;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
+    TCPHdr tcph;
+    PacketQueue pq;
+    memset(&pq,0,sizeof(PacketQueue));
+    memset(p, 0, SIZE_OF_PACKET);
+    memset (&f, 0, sizeof(Flow));
+    memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
+
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
+    p->tcph = &tcph;
+
+    int ret = 0;
+
+    StreamTcpInitConfig(TRUE);
+
+    /* handshake */
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+
+    TcpSession *ssn = (TcpSession *)f.protoctx;
+
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
+        goto end;
+    }
+
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* partial request */
+    uint8_t request1[] = { 0x47, 0x45, };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request1);
+    p->payload = request1;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+    /* response ack against partial request */
+    p->tcph->th_ack = htonl(3);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    /* complete partial request */
+    uint8_t request2[] = {
+        0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
+        0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
+        0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
+        0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
+        0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
+        0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
+        0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
+        0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
+        0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
+        0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(3);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request2);
+    p->payload = request2;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 6\n");
+        goto end;
+    }
+
+    /* response - request ack */
+    uint8_t response[] = {
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(88);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response);
+    p->payload = response;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 7\n");
+        goto end;
+    }
+
+    /* response ack */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(88);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 8\n");
+        goto end;
+    }
+
+    StreamTcpSessionClear(p->flow->protoctx);
+
+    ret = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    SCFree(p);
+    return ret;
+}
+
+/**
+ * \test GET -> RUBBISH(PM AND PP DONE IN ONE GO)
+ */
+ static int AppLayerTest03(void)
+{
+    Packet *p = SCMalloc(SIZE_OF_PACKET);
+    if (unlikely(p == NULL))
+        return 0;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
+    TCPHdr tcph;
+    PacketQueue pq;
+    memset(&pq,0,sizeof(PacketQueue));
+    memset(p, 0, SIZE_OF_PACKET);
+    memset (&f, 0, sizeof(Flow));
+    memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
+
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
+    p->tcph = &tcph;
+
+    int ret = 0;
+
+    StreamTcpInitConfig(TRUE);
+
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+
+    TcpSession *ssn = (TcpSession *)f.protoctx;
+
+    /* handshake */
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* request */
+    uint8_t request[] = {
+        0x47, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
+        0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
+        0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
+        0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
+        0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
+        0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
+        0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
+        0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
+        0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
+        0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request);
+    p->payload = request;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+    /* rubbish response */
+    uint8_t response[] = {
+        0x58, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(88);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response);
+    p->payload = response;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    /* response ack */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(88);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 6\n");
+        goto end;
+    }
+
+    StreamTcpSessionClear(p->flow->protoctx);
+
+    ret = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    SCFree(p);
+    return ret;
+}
+
+/**
+ * \test GE -> RUBBISH(TC - PM AND PP NOT DONE) -> RUBBISH(TC - PM AND PP DONE).
+ */
+static int AppLayerTest04(void)
+{
+    Packet *p = SCMalloc(SIZE_OF_PACKET);
+    if (unlikely(p == NULL))
+        return 0;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
+    TCPHdr tcph;
+    PacketQueue pq;
+    memset(&pq,0,sizeof(PacketQueue));
+    memset(p, 0, SIZE_OF_PACKET);
+    memset (&f, 0, sizeof(Flow));
+    memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
+
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
+    p->tcph = &tcph;
+
+    int ret = 0;
+
+    StreamTcpInitConfig(TRUE);
+
+    /* handshake */
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+
+    TcpSession *ssn = (TcpSession *)f.protoctx;
+
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* request */
+    uint8_t request[] = {
+        0x47, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
+        0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
+        0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
+        0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
+        0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
+        0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
+        0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
+        0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
+        0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
+        0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request);
+    p->payload = request;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+    /* partial response */
+    uint8_t response1[] = { 0x58, 0x54, 0x54, 0x50, };
+    p->tcph->th_ack = htonl(88);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response1);
+    p->payload = response1;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    /* partial response ack */
+    p->tcph->th_ack = htonl(5);
+    p->tcph->th_seq = htonl(88);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 4 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 6\n");
+        goto end;
+    }
+
+    /* remaining response */
+    uint8_t response2[] = {
+        0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(88);
+    p->tcph->th_seq = htonl(5);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response2);
+    p->payload = response2;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 4 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 7\n");
+        goto end;
+    }
+
+    /* response ack */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(88);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 8\n");
+        goto end;
+    }
+
+    StreamTcpSessionClear(p->flow->protoctx);
+
+    ret = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    SCFree(p);
+    return ret;
+}
+
+/**
+ * \test RUBBISH -> HTTP/1.1
+ */
+static int AppLayerTest05(void)
+{
+    Packet *p = SCMalloc(SIZE_OF_PACKET);
+    if (unlikely(p == NULL))
+        return 0;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
+    TCPHdr tcph;
+    PacketQueue pq;
+    memset(&pq,0,sizeof(PacketQueue));
+    memset(p, 0, SIZE_OF_PACKET);
+    memset (&f, 0, sizeof(Flow));
+    memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
+
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
+    p->tcph = &tcph;
+
+    int ret = 0;
+
+    StreamTcpInitConfig(TRUE);
+
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+
+    TcpSession *ssn = (TcpSession *)f.protoctx;
+
+    /* handshake */
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
+        goto end;
+    }
+
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* full request */
+    uint8_t request[] = {
+        0x48, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
+        0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
+        0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
+        0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
+        0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
+        0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
+        0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
+        0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
+        0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
+        0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request);
+    p->payload = request;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+    /* full response - request ack */
+    uint8_t response[] = {
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(88);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response);
+    p->payload = response;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    /* response ack */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(88);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 6\n");
+        goto end;
+    }
+
+    StreamTcpSessionClear(p->flow->protoctx);
+
+    ret = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    SCFree(p);
+    return ret;
+}
+
+/**
+ * \test HTTP/1.1 -> GET
+ */
+static int AppLayerTest06(void)
+{
+    Packet *p = SCMalloc(SIZE_OF_PACKET);
+    if (unlikely(p == NULL))
+        return 0;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
+    TCPHdr tcph;
+    PacketQueue pq;
+    memset(&pq,0,sizeof(PacketQueue));
+    memset(p, 0, SIZE_OF_PACKET);
+    memset (&f, 0, sizeof(Flow));
+    memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
+
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
+    p->tcph = &tcph;
+
+    int ret = 0;
+
+    StreamTcpInitConfig(TRUE);
+
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+
+    TcpSession *ssn = (TcpSession *)f.protoctx;
+
+    /* handshake */
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
+        goto end;
+    }
+
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* full response - request ack */
+    uint8_t response[] = {
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response);
+    p->payload = response;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOCLIENT) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+    /* full request - response ack*/
+    uint8_t request[] = {
+        0x47, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
+        0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
+        0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
+        0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
+        0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
+        0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
+        0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
+        0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
+        0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
+        0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request);
+    p->payload = request;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        !(f.flags & FLOW_NO_APPLAYER_INSPECTION) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    StreamTcpSessionClear(p->flow->protoctx);
+
+    ret = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    SCFree(p);
+    return ret;
+}
+
+/**
+ * \test GET -> DCERPC
+ */
+static int AppLayerTest07(void)
+{
+    Packet *p = SCMalloc(SIZE_OF_PACKET);
+    if (unlikely(p == NULL))
+        return 0;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
+    TCPHdr tcph;
+    PacketQueue pq;
+    memset(&pq,0,sizeof(PacketQueue));
+    memset(p, 0, SIZE_OF_PACKET);
+    memset (&f, 0, sizeof(Flow));
+    memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
+
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
+    p->tcph = &tcph;
+
+    int ret = 0;
+
+    StreamTcpInitConfig(TRUE);
+
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+
+    TcpSession *ssn = (TcpSession *)f.protoctx;
+
+    /* handshake */
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
+        goto end;
+    }
+
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* full request */
+    uint8_t request[] = {
+        0x47, 0x45, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
+        0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
+        0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
+        0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
+        0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
+        0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
+        0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
+        0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
+        0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
+        0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request);
+    p->payload = request;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+    /* full response - request ack */
+    uint8_t response[] = {
+        0x05, 0x00, 0x4d, 0x42, 0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(88);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response);
+    p->payload = response;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    /* response ack */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(88);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        !(f.flags & FLOW_NO_APPLAYER_INSPECTION) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 6\n");
+        goto end;
+    }
+
+    StreamTcpSessionClear(p->flow->protoctx);
+
+    ret = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    SCFree(p);
+    return ret;
+}
+
+/**
+ * \test SMB -> HTTP/1.1
+ */
+static int AppLayerTest08(void)
+{
+    Packet *p = SCMalloc(SIZE_OF_PACKET);
+    if (unlikely(p == NULL))
+        return 0;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
+    TCPHdr tcph;
+    PacketQueue pq;
+    memset(&pq,0,sizeof(PacketQueue));
+    memset(p, 0, SIZE_OF_PACKET);
+    memset (&f, 0, sizeof(Flow));
+    memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
+
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
+    p->tcph = &tcph;
+
+    int ret = 0;
+
+    StreamTcpInitConfig(TRUE);
+
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+
+    TcpSession *ssn = (TcpSession *)f.protoctx;
+
+    /* handshake */
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
+        goto end;
+    }
+
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* full request */
+    uint8_t request[] = {
+        0x05, 0x00, 0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
+        0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
+        0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
+        0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
+        0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
+        0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
+        0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
+        0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
+        0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
+        0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request);
+    p->payload = request;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+    /* full response - request ack */
+    uint8_t response[] = {
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(88);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response);
+    p->payload = response;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_DCERPC ||
+        f.alproto_ts != ALPROTO_DCERPC ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    /* response ack */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(88);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        !(f.flags & FLOW_NO_APPLAYER_INSPECTION) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 6\n");
+        goto end;
+    }
+
+    StreamTcpSessionClear(p->flow->protoctx);
+
+    ret = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    SCFree(p);
+    return ret;
+}
+
+/**
+ * \test RUBBISH(TC - PM and PP NOT DONE) ->
+ *       RUBBISH(TC - PM and PP DONE) ->
+ *       RUBBISH(TS - PM and PP DONE)
+ */
+static int AppLayerTest09(void)
+{
+    Packet *p = SCMalloc(SIZE_OF_PACKET);
+    if (unlikely(p == NULL))
+        return 0;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
+    TCPHdr tcph;
+    PacketQueue pq;
+    memset(&pq,0,sizeof(PacketQueue));
+    memset(p, 0, SIZE_OF_PACKET);
+    memset (&f, 0, sizeof(Flow));
+    memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
+
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
+    p->tcph = &tcph;
+
+    int ret = 0;
+
+    StreamTcpInitConfig(TRUE);
+
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+
+    TcpSession *ssn = (TcpSession *)f.protoctx;
+
+    /* handshake */
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
+        goto end;
+    }
+
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* full request */
+    uint8_t request1[] = {
+        0x47, 0x47, 0x49, 0x20, 0x2f, 0x69, 0x6e, 0x64 };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request1);
+    p->payload = request1;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+    /* response - request ack */
+    p->tcph->th_ack = htonl(9);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    /* full request */
+    uint8_t request2[] = {
+        0x44, 0x44, 0x45, 0x20, 0x2f, 0x69, 0x6e, 0x64 };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(9);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request2);
+    p->payload = request2;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 6\n");
+        goto end;
+    }
+
+    /* full response - request ack */
+    uint8_t response[] = {
+        0x55, 0x74, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(17);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response);
+    p->payload = response;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 7\n");
+        goto end;
+    }
+
+    /* response ack */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(17);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        !(f.flags & FLOW_NO_APPLAYER_INSPECTION) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 8\n");
+        goto end;
+    }
+
+    StreamTcpSessionClear(p->flow->protoctx);
+
+    ret = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    SCFree(p);
+    return ret;
+}
+
+/**
+ * \test RUBBISH(TC - PM and PP DONE) ->
+ *       RUBBISH(TS - PM and PP DONE)
+ */
+static int AppLayerTest10(void)
+{
+    Packet *p = SCMalloc(SIZE_OF_PACKET);
+    if (unlikely(p == NULL))
+        return 0;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
+    TCPHdr tcph;
+    PacketQueue pq;
+    memset(&pq,0,sizeof(PacketQueue));
+    memset(p, 0, SIZE_OF_PACKET);
+    memset (&f, 0, sizeof(Flow));
+    memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
+
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
+    p->tcph = &tcph;
+
+    int ret = 0;
+
+    StreamTcpInitConfig(TRUE);
+
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+
+    TcpSession *ssn = (TcpSession *)f.protoctx;
+
+    /* handshake */
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
+        goto end;
+    }
+
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* full request */
+    uint8_t request1[] = {
+        0x47, 0x47, 0x49, 0x20, 0x2f, 0x69, 0x6e, 0x64,
+        0x47, 0x47, 0x49, 0x20, 0x2f, 0x69, 0x6e, 0x64 };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request1);
+    p->payload = request1;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+    /* response - request ack */
+    p->tcph->th_ack = htonl(17);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    /* full response - request ack */
+    uint8_t response[] = {
+        0x55, 0x74, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(17);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response);
+    p->payload = response;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 7\n");
+        goto end;
+    }
+
+    /* response ack */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(17);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        !(f.flags & FLOW_NO_APPLAYER_INSPECTION) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 8\n");
+        goto end;
+    }
+
+    StreamTcpSessionClear(p->flow->protoctx);
+
+    ret = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    SCFree(p);
+    return ret;
+}
+
+/**
+ * \test RUBBISH(TC - PM and PP DONE) ->
+ *       RUBBISH(TS - PM and PP NOT DONE) ->
+ *       RUBBISH(TS - PM and PP DONE)
+ */
+static int AppLayerTest11(void)
+{
+    Packet *p = SCMalloc(SIZE_OF_PACKET);
+    if (unlikely(p == NULL))
+        return 0;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
+    TCPHdr tcph;
+    PacketQueue pq;
+    memset(&pq,0,sizeof(PacketQueue));
+    memset(p, 0, SIZE_OF_PACKET);
+    memset (&f, 0, sizeof(Flow));
+    memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
+
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
+    p->tcph = &tcph;
+
+    int ret = 0;
+
+    StreamTcpInitConfig(TRUE);
+
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+
+    TcpSession *ssn = (TcpSession *)f.protoctx;
+
+    /* handshake */
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
+        goto end;
+    }
+
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* full request */
+    uint8_t request1[] = {
+        0x47, 0x47, 0x49, 0x20, 0x2f, 0x69, 0x6e, 0x64,
+        0x47, 0x47, 0x49, 0x20, 0x2f, 0x69, 0x6e, 0x64 };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request1);
+    p->payload = request1;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+    /* response - request ack */
+    p->tcph->th_ack = htonl(17);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    /* full response - request ack */
+    uint8_t response1[] = {
+        0x55, 0x74, 0x54, 0x50, };
+    p->tcph->th_ack = htonl(17);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response1);
+    p->payload = response1;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 6\n");
+        goto end;
+    }
+
+    /* response ack from request */
+    p->tcph->th_ack = htonl(5);
+    p->tcph->th_seq = htonl(17);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 7\n");
+        goto end;
+    }
+
+    uint8_t response2[] = {
+        0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(17);
+    p->tcph->th_seq = htonl(5);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response2);
+    p->payload = response2;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 8\n");
+        goto end;
+    }
+
+    /* response ack from request */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(17);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        !(f.flags & FLOW_NO_APPLAYER_INSPECTION) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || !FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 9\n");
+        goto end;
+    }
+
+    StreamTcpSessionClear(p->flow->protoctx);
+
+    ret = 1;
+end:
+    StreamTcpFreeConfig(TRUE);
+    SCFree(p);
+    return ret;
+}
+
+#endif
+
+void AppLayerRegisterUnittests(void)
+{
+#ifdef UNITTESTS
+    UtRegisterTest("AppLayerTest01", AppLayerTest01, 1);
+    UtRegisterTest("AppLayerTest02", AppLayerTest02, 1);
+    UtRegisterTest("AppLayerTest03", AppLayerTest03, 1);
+    UtRegisterTest("AppLayerTest04", AppLayerTest04, 1);
+    UtRegisterTest("AppLayerTest05", AppLayerTest05, 1);
+    UtRegisterTest("AppLayerTest06", AppLayerTest06, 1);
+    UtRegisterTest("AppLayerTest07", AppLayerTest07, 1);
+    UtRegisterTest("AppLayerTest08", AppLayerTest08, 1);
+    UtRegisterTest("AppLayerTest09", AppLayerTest09, 1);
+    UtRegisterTest("AppLayerTest10", AppLayerTest10, 1);
+    UtRegisterTest("AppLayerTest11", AppLayerTest11, 1);
+#endif
+
+    return;
+}
index 4465ce825619aec702f01042cffd010c6b971797..047aca94338e15d6a6173b59b878c853d8ffc26b 100644 (file)
 uint16_t AppLayerGetProtoFromPacket(Packet *);
 void *AppLayerGetProtoStateFromPacket(Packet *);
 void *AppLayerGetProtoStateFromFlow(Flow *);
-int AppLayerHandleTCPData(AlpProtoDetectThreadCtx *, Flow *, TcpSession *, TcpStream *, uint8_t *, uint32_t, uint8_t);
+int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, Flow *f,
+                          TcpSession *ssn, TcpStream *stream, uint8_t *data, uint32_t data_len, Packet *p, uint8_t flags);
 int AppLayerHandleTCPMsg(AlpProtoDetectThreadCtx *, StreamMsg *);
 //int AppLayerHandleMsg(AlpProtoDetectThreadCtx *, StreamMsg *);
 int AppLayerHandleUdp(AlpProtoDetectThreadCtx *, Flow *, Packet *p);
 
+void AppLayerRegisterUnittests(void);
+
 #endif /* __APP_LAYER_H__ */
 
index 09a177c8450e8e251f4f0c9b06db82a6ef1e4535..03cf4718483aa401bd760d779dd049ed61ca2344 100644 (file)
         FLOWLOCK_INIT((f)); \
         (f)->protoctx = NULL; \
         (f)->alproto = 0; \
+        (f)->alproto_ts = 0; \
+        (f)->alproto_tc = 0; \
+        (f)->data_al_so_far[0] = 0; \
+        (f)->data_al_so_far[1] = 0; \
         (f)->de_ctx_id = 0; \
         (f)->alparser = NULL; \
         (f)->alstate = NULL; \
         (f)->alparser = NULL; \
         (f)->alstate = NULL; \
         (f)->alproto = 0; \
+        (f)->alproto_ts = 0; \
+        (f)->alproto_tc = 0; \
+        (f)->data_al_so_far[0] = 0; \
+        (f)->data_al_so_far[1] = 0; \
         (f)->de_ctx_id = 0; \
         if ((f)->de_state != NULL) { \
             DetectEngineStateReset((f)->de_state, (STREAM_TOSERVER | STREAM_TOCLIENT)); \
index 98080626d0f85ac5e7507925c149020ee8c51108..ddde8584620176871d6c8b987fce0df29c9869a6 100644 (file)
@@ -327,6 +327,10 @@ typedef struct Flow_
     uint8_t pad0;
 
     uint16_t alproto; /**< \brief application level protocol */
+    uint16_t alproto_ts;
+    uint16_t alproto_tc;
+
+    uint32_t data_al_so_far[2];
 
     /** detection engine ctx id used to inspect this flow. Set at initial
      *  inspection. If it doesn't match the currently in use de_ctx, the
index 8113da5c0a7584e5d907af5b5c1dd92d71947153..b58abcbd8c3070a62074a11b11b003079f33cae4 100644 (file)
@@ -63,6 +63,7 @@
 
 #include "app-layer-detect-proto.h"
 #include "app-layer-parser.h"
+#include "app-layer.h"
 #include "app-layer-smb.h"
 #include "app-layer-dcerpc.h"
 #include "app-layer-dcerpc-udp.h"
@@ -257,6 +258,7 @@ int RunUnittests(int list_unittests, char *regex_arg)
 #ifdef __SC_CUDA_SUPPORT__
     CudaBufferRegisterUnittests();
 #endif
+    AppLayerRegisterUnittests();
     if (list_unittests) {
         UtListTests(regex_arg);
     } else {
index 5296ec3dd8c34ff9c34b7ff80d082426ddce546c..6e9f9922c4cd8591d1cb3f3cc96d82302f790c7d 100644 (file)
@@ -215,6 +215,8 @@ typedef struct TcpSession_ {
     struct StreamMsg_ *toclient_smsg_head;  /**< list of stream msgs (for detection inspection) */
     struct StreamMsg_ *toclient_smsg_tail;  /**< list of stream msgs (for detection inspection) */
 
+    int8_t data_first_seen_dir;
+
     TcpStateQueue *queue;                   /**< list of SYN/ACK candidates */
 } TcpSession;
 
index f3dc9e3e38f20072ea0a3a3c01e591b12697c0f5..53267d7c8883e8c6b210c9485734abdac727bcbb 100644 (file)
@@ -1630,6 +1630,14 @@ int StreamTcpReassembleHandleSegmentHandleData(ThreadVars *tv, TcpReassemblyThre
 {
     SCEnter();
 
+    if (ssn->data_first_seen_dir == 0) {
+        if (p->flowflags & FLOW_PKT_TOSERVER) {
+            ssn->data_first_seen_dir = STREAM_TOSERVER;
+        } else {
+            ssn->data_first_seen_dir = STREAM_TOCLIENT;
+        }
+    }
+
     /* If we have reached the defined depth for either of the stream, then stop
        reassembling the TCP session */
     uint32_t size = StreamTcpReassembleCheckDepth(stream, TCP_GET_SEQ(p), p->payload_len);
@@ -1856,8 +1864,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv,
             SCLogDebug("sending empty eof message");
             /* send EOF to app layer */
             STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags);
-            AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                    NULL, 0, flags);
+            AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                                  NULL, 0, p, flags);
             PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
 
         } else {
@@ -1935,8 +1943,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv,
                 STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags);
 
                 /* process what we have so far */
-                AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                        data, data_len, flags);
+                AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                                      data, data_len, p, flags);
                 PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
 
                 data_sent += data_len;
@@ -1964,8 +1972,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv,
 
                 /* send gap signal */
                 STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags);
-                AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                        NULL, 0, flags|STREAM_GAP);
+                AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                                      NULL, 0, p, flags|STREAM_GAP);
                 PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
                 data_len = 0;
 
@@ -2036,8 +2044,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv,
                 /* process what we have so far */
                 STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags);
                 BUG_ON(data_len > sizeof(data));
-                AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                        data, data_len, flags);
+                AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                                      data, data_len, p, flags);
                 PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
                 data_sent += data_len;
                 data_len = 0;
@@ -2090,8 +2098,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv,
                         /* process what we have so far */
                         STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags);
                         BUG_ON(data_len > sizeof(data));
-                        AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                                data, data_len, flags);
+                        AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                                              data, data_len, p, flags);
                         PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
                         data_sent += data_len;
                         data_len = 0;
@@ -2126,8 +2134,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv,
         /* process what we have so far */
         STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags);
         BUG_ON(data_len > sizeof(data));
-        AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                data, data_len, flags);
+        AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                              data, data_len, p, flags);
         PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
         data_sent += data_len;
     }
@@ -2136,8 +2144,8 @@ static int StreamTcpReassembleInlineAppLayer (ThreadVars *tv,
         SCLogDebug("sending empty eof message");
         /* send EOF to app layer */
         STREAM_SET_INLINE_FLAGS(ssn, stream, p, flags);
-        AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                NULL, 0, flags);
+        AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                              NULL, 0, p, flags);
         PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
     }
 
@@ -2570,9 +2578,9 @@ void StreamTcpPruneSession(Flow *f, uint8_t flags) {
  *
  *  \todo this function is too long, we need to break it up. It needs it BAD
  */
-static int StreamTcpReassembleAppLayer (ThreadVars *tv,
-        TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream,
-        Packet *p)
+int StreamTcpReassembleAppLayer (ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
+                                 TcpSession *ssn, TcpStream *stream,
+                                 Packet *p)
 {
     SCEnter();
 
@@ -2595,8 +2603,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv,
             SCLogDebug("sending empty eof message");
             /* send EOF to app layer */
             STREAM_SET_FLAGS(ssn, stream, p, flags);
-            AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                    NULL, 0, flags);
+            AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                                  NULL, 0, p, flags);
             PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
 
             SCReturnInt(0);
@@ -2699,8 +2707,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv,
                 STREAM_SET_FLAGS(ssn, stream, p, flags);
 
                 /* process what we have so far */
-                AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                        data, data_len, flags);
+                AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                                      data, data_len, p, flags);
                 PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
                 data_len = 0;
             }
@@ -2726,8 +2734,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv,
 
                 /* send gap signal */
                 STREAM_SET_FLAGS(ssn, stream, p, flags);
-                AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                        NULL, 0, flags|STREAM_GAP);
+                AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                                      NULL, 0, p, flags|STREAM_GAP);
                 PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
                 data_len = 0;
 
@@ -2823,8 +2831,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv,
                 /* process what we have so far */
                 STREAM_SET_FLAGS(ssn, stream, p, flags);
                 BUG_ON(data_len > sizeof(data));
-                AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                        data, data_len, flags);
+                AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                                      data, data_len, p, flags);
                 PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
                 data_len = 0;
 
@@ -2883,8 +2891,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv,
                         /* process what we have so far */
                         STREAM_SET_FLAGS(ssn, stream, p, flags);
                         BUG_ON(data_len > sizeof(data));
-                        AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                                data, data_len, flags);
+                        AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                                              data, data_len, p, flags);
                         PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
                         data_len = 0;
 
@@ -2930,8 +2938,8 @@ static int StreamTcpReassembleAppLayer (ThreadVars *tv,
         /* process what we have so far */
         STREAM_SET_FLAGS(ssn, stream, p, flags);
         BUG_ON(data_len > sizeof(data));
-        AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, stream,
-                data, data_len, flags);
+        AppLayerHandleTCPData(tv, ra_ctx, p->flow, ssn, stream,
+                              data, data_len, p, flags);
         PACKET_PROFILING_APP_STORE(&ra_ctx->dp_ctx, p);
     }
 
@@ -5997,9 +6005,16 @@ static int StreamTcpReassembleTest37(void) {
  *          until the app layer protocol has been detected and one smsg from
  *          toserver side has been sent to app layer.
  *
+ * Unittest modified by commit -
+ *
+ * commit bab1636377bb4f1b7b889f4e3fd594795085eaa4
+ * Author: Anoop Saldanha <anoopsaldanha@gmail.com>
+ * Date:   Fri Feb 15 18:58:33 2013 +0530
+ *
+ *     Improved app protocol detection.
+ *
  *  \retval On success it returns 1 and on failure 0.
  */
-
 static int StreamTcpReassembleTest38 (void) {
     int ret = 0;
     Packet *p = PacketGetFromAlloc();
@@ -6022,12 +6037,12 @@ static int StreamTcpReassembleTest38 (void) {
     StreamTcpInitConfig(TRUE);
     TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx();
 
-    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\n";
-    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
-
-    uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
+    uint8_t httpbuf2[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\n";
     uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
 
+    uint8_t httpbuf1[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
+    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
+
     FLOW_INITIALIZE(&f);
     if (inet_pton(AF_INET, "1.2.3.4", &in) != 1)
         goto end;
@@ -6057,7 +6072,7 @@ static int StreamTcpReassembleTest38 (void) {
     tcph.th_ack = htonl(20);
     tcph.th_flags = TH_ACK|TH_PUSH;
     p->tcph = &tcph;
-    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->flowflags = FLOW_PKT_TOSERVER;
 
     p->payload = httpbuf2;
     p->payload_len = httplen2;
@@ -6078,7 +6093,7 @@ static int StreamTcpReassembleTest38 (void) {
         goto end;
     }
 
-    p->flowflags = FLOW_PKT_TOSERVER;
+    p->flowflags = FLOW_PKT_TOCLIENT;
     p->payload = httpbuf1;
     p->payload_len = httplen1;
     tcph.th_seq = htonl(10);
@@ -6091,53 +6106,11 @@ static int StreamTcpReassembleTest38 (void) {
     }
 
     /* Check if we have stream smsgs in queue */
-    if (ra_ctx->stream_q->len > 0) {
-        printf("there shouldn't be any stream smsgs in the queue, as we didn't"
-                " processed any smsg from toserver side till yet (4): ");
-        goto end;
-    }
-
-    p->flowflags = FLOW_PKT_TOCLIENT;
-    p->payload = httpbuf2;
-    p->payload_len = httplen2;
-    tcph.th_seq = htonl(55);
-    tcph.th_ack = htonl(53);
-    s = &ssn.server;
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet (5): ");
-        goto end;
-    }
-
-    /* we should now have a smsg as the http request is complete and triggered
-     * reassembly */
     if (ra_ctx->stream_q->len != 1) {
         printf("there should one stream smsg in the queue (6): ");
         goto end;
     }
 
-    p->flowflags = FLOW_PKT_TOSERVER;
-    p->payload = httpbuf1;
-    p->payload_len = httplen1;
-    tcph.th_seq = htonl(53);
-    tcph.th_ack = htonl(100);
-    s = &ssn.client;
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet (8): ");
-        goto end;
-    }
-
-    p->flowflags = FLOW_PKT_TOCLIENT;
-    p->payload = NULL;
-    p->payload_len = 0;
-    tcph.th_seq = htonl(100);
-    tcph.th_ack = htonl(53);
-    s = &ssn.server;
-
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet (9): ");
-        goto end;
-    }
-
     ret = 1;
 end:
     StreamTcpReassembleFreeThreadCtx(ra_ctx);
@@ -6156,205 +6129,590 @@ end:
  */
 
 static int StreamTcpReassembleTest39 (void) {
-    SCEnter();
-
-    int ret = 0;
     Packet *p = PacketGetFromAlloc();
     if (unlikely(p == NULL))
         return 0;
-    Flow *f = NULL;
+    Flow f;
+    ThreadVars tv;
+    StreamTcpThread *stt = NULL;
     TCPHdr tcph;
-    TcpSession ssn;
     PacketQueue pq;
     memset(&pq,0,sizeof(PacketQueue));
-    memset(&tcph, 0, sizeof (TCPHdr));
-    memset(&ssn, 0, sizeof(TcpSession));
-    ThreadVars tv;
+    memset (&f, 0, sizeof(Flow));
     memset(&tv, 0, sizeof (ThreadVars));
+    StreamTcpThreadInit(&tv, NULL, (void **)&stt);
+    memset(&tcph, 0, sizeof (TCPHdr));
 
-    StreamTcpInitConfig(TRUE);
-    TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx();
-    StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 7);
-    StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 7);
-
-    uint8_t httpbuf1[] = "POST / HTTP/1.0\r\nUser-Agent: Victor/1.0\r\n\r\n";
-    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
-
-    uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
-    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
-
-    ssn.server.ra_raw_base_seq = ssn.server.ra_app_base_seq = 9;
-    ssn.server.isn = 9;
-    ssn.server.last_ack = 160;
-    ssn.client.ra_raw_base_seq = ssn.client.ra_app_base_seq= 9;
-    ssn.client.isn = 9;
-    ssn.client.last_ack = 160;
-
-    f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
-    if (f == NULL)
-        goto end;
-    f->protoctx = &ssn;
-    p->flow = f;
-
-    SCLogDebug("check client seg list %p", ssn.client.seg_list);
-    tcph.th_win = htons(5480);
-    tcph.th_seq = htonl(10);
-    tcph.th_ack = htonl(20);
-    tcph.th_flags = TH_ACK|TH_PUSH;
+    f.flags = FLOW_IPV4;
+    p->pkt = (uint8_t *)(p + 1);
+    p->flow = &f;
     p->tcph = &tcph;
-    p->flowflags = FLOW_PKT_TOCLIENT;
 
-    p->payload = httpbuf2;
-    p->payload_len = httplen2;
-    ssn.state = TCP_ESTABLISHED;
-
-    TcpStream *s = NULL;
-    s = &ssn.server;
-
-    SCMutexLock(&f->m);
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet (1): ");
-        goto end;
-    }
+    SCMutexLock(&f.m);
+    int ret = 0;
 
-    /* Check if we have stream smsgs in queue */
-    if (ra_ctx->stream_q->len > 0) {
-        printf("there shouldn't be any stream smsgs in the queue: (2): ");
-        goto end;
-    }
+    StreamTcpInitConfig(TRUE);
 
-    SCLogDebug("check client seg list %p", ssn.client.seg_list);
+    /* handshake */
+    tcph.th_win = htons(5480);
+    tcph.th_flags = TH_SYN;
     p->flowflags = FLOW_PKT_TOSERVER;
-    p->payload = httpbuf1;
-    p->payload_len = httplen1;
-    tcph.th_seq = htonl(10);
-    tcph.th_ack = htonl(55);
-    s = &ssn.client;
-
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet (3): ");
-        goto end;
-    }
-
-    /* Check if we have stream smsgs in queue */
-    if (ra_ctx->stream_q->len == 0) {
-        printf("there should be stream smsgs in the queue (4): ");
-        goto end;
-    }
-    SCLogDebug("check client seg list %p", ssn.client.seg_list);
-
-
-    p->flowflags = FLOW_PKT_TOCLIENT;
-    p->payload = httpbuf2;
-    p->payload_len = httplen2;
-    tcph.th_seq = htonl(55);
-    tcph.th_ack = htonl(53);
-    s = &ssn.server;
-
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet (5): ");
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
         goto end;
-    }
-    SCLogDebug("check client seg list %p", ssn.client.seg_list);
 
+    TcpSession *ssn = (TcpSession *)f.protoctx;
 
-    /* Check if we have stream smsgs in queue */
-    SCLogDebug("check if we have stream smsgs in queue");
-    if (ra_ctx->stream_q->len == 0) {
-        printf("there should be a stream smsgs in the queue (6): ");
-        goto end;
-    }
-
-    SCLogDebug("check client seg list %p", ssn.client.seg_list);
-    /* Process stream smsgs we may have in queue */
-    SCLogDebug("process stream smsgs we may have in queue");
-    if (StreamTcpReassembleProcessAppLayer(ra_ctx) < 0) {
-        printf("failed in processing stream smsgs (7): ");
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list != NULL ||
+        ssn->server.seg_list != NULL ||
+        stt->ra_ctx->stream_q->len != 0 ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 1\n");
         goto end;
     }
 
-    SCLogDebug("check client seg list %p", ssn.client.seg_list);
-
-    /* check is have the segment in the list and flagged or not */
-/*
-    if (ssn.client.seg_list == NULL ||
-            !(ssn.client.seg_list->flags & SEGMENTTCP_FLAG_RAW_PROCESSED))
-    {
-        printf("the list is NULL or the processed segment has not been flaged (8), seg %p, flags %02X: ",
-                ssn.client.seg_list, ssn.client.seg_list? ssn.client.seg_list->flags:0);
-//abort();
-        goto end;
-    }
-*/
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_flags = TH_SYN | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list != NULL ||
+        ssn->server.seg_list != NULL ||
+        stt->ra_ctx->stream_q->len != 0 ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 2\n");
+        goto end;
+    }
+
+    /* handshake */
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
     p->flowflags = FLOW_PKT_TOSERVER;
-    p->payload = httpbuf1;
-    p->payload_len = httplen1;
-    tcph.th_seq = htonl(53);
-    tcph.th_ack = htonl(100);
-    s = &ssn.client;
-
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet (9): ");
-        goto end;
-    }
-
-    /* Check if we have stream smsgs in queue */
-    if (ra_ctx->stream_q->len == 0 &&
-            !(ssn.client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED)) {
-        printf("there should be a stream smsgs in the queue, as we have detected"
-                " the app layer protocol and one smsg from toserver side has "
-                "been sent (10): ");
-        goto end;
-    /* Process stream smsgs we may have in queue */
-    } else if (StreamTcpReassembleProcessAppLayer(ra_ctx) < 0) {
-        printf("failed in processing stream smsgs (11): ");
-        goto end;
-    }
-
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list != NULL ||
+        ssn->server.seg_list != NULL ||
+        stt->ra_ctx->stream_q->len != 0 ||
+        ssn->data_first_seen_dir != 0) {
+        printf("failure 3\n");
+        goto end;
+    }
+
+    /* partial request */
+    uint8_t request1[] = { 0x47, 0x45, };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request1);
+    p->payload = request1;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list == NULL ||
+        ssn->client.seg_list->next != NULL ||
+        ssn->server.seg_list != NULL ||
+        stt->ra_ctx->stream_q->len != 0 ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 4\n");
+        goto end;
+    }
+
+
+    /* response ack against partial request */
+    p->tcph->th_ack = htonl(3);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_ACK;
     p->flowflags = FLOW_PKT_TOCLIENT;
-    p->payload = httpbuf2;
-    p->payload_len = httplen2;
-    tcph.th_seq = htonl(100);
-    tcph.th_ack = htonl(96);
-    s = &ssn.server;
-
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet (12): ");
-        goto end;
-    }
-
-    SCLogDebug("final check");
-
-    if (!(ssn.client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED)) {
-        printf("STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED flag should have been set (13): ");
-        goto end;
-    }
-
-    /* check if the segment in the list is flagged or not */
-    if (ssn.client.seg_list == NULL) {
-        printf("segment list should not be empty (14): ");
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list == NULL ||
+        ssn->client.seg_list->next != NULL ||
+        ssn->server.seg_list != NULL ||
+        stt->ra_ctx->stream_q->len != 0 ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 5\n");
+        goto end;
+    }
+
+    /* complete partial request */
+    uint8_t request2[] = {
+        0x54, 0x20, 0x2f, 0x69, 0x6e, 0x64,
+        0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20,
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30,
+        0x0d, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x20,
+        0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
+        0x74, 0x0d, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x2d,
+        0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x41,
+        0x70, 0x61, 0x63, 0x68, 0x65, 0x42, 0x65, 0x6e,
+        0x63, 0x68, 0x2f, 0x32, 0x2e, 0x33, 0x0d, 0x0a,
+        0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3a, 0x20,
+        0x2a, 0x2f, 0x2a, 0x0d, 0x0a, 0x0d, 0x0a };
+    p->tcph->th_ack = htonl(1);
+    p->tcph->th_seq = htonl(3);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request2);
+    p->payload = request2;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        f.alproto != ALPROTO_UNKNOWN ||
+        f.alproto_ts != ALPROTO_UNKNOWN ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list == NULL ||
+        ssn->client.seg_list->next == NULL ||
+        ssn->client.seg_list->next->next != NULL ||
+        ssn->server.seg_list != NULL ||
+        stt->ra_ctx->stream_q->len != 0 ||
+        ssn->data_first_seen_dir != STREAM_TOSERVER) {
+        printf("failure 6\n");
+        goto end;
+    }
+
+    /* response - request ack */
+    uint8_t response[] = {
+        0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31,
+        0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0x0d,
+        0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x46,
+        0x72, 0x69, 0x2c, 0x20, 0x32, 0x33, 0x20, 0x53,
+        0x65, 0x70, 0x20, 0x32, 0x30, 0x31, 0x31, 0x20,
+        0x30, 0x36, 0x3a, 0x32, 0x39, 0x3a, 0x33, 0x39,
+        0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x53, 0x65,
+        0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x41, 0x70,
+        0x61, 0x63, 0x68, 0x65, 0x2f, 0x32, 0x2e, 0x32,
+        0x2e, 0x31, 0x35, 0x20, 0x28, 0x55, 0x6e, 0x69,
+        0x78, 0x29, 0x20, 0x44, 0x41, 0x56, 0x2f, 0x32,
+        0x0d, 0x0a, 0x4c, 0x61, 0x73, 0x74, 0x2d, 0x4d,
+        0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x3a,
+        0x20, 0x54, 0x68, 0x75, 0x2c, 0x20, 0x30, 0x34,
+        0x20, 0x4e, 0x6f, 0x76, 0x20, 0x32, 0x30, 0x31,
+        0x30, 0x20, 0x31, 0x35, 0x3a, 0x30, 0x34, 0x3a,
+        0x34, 0x36, 0x20, 0x47, 0x4d, 0x54, 0x0d, 0x0a,
+        0x45, 0x54, 0x61, 0x67, 0x3a, 0x20, 0x22, 0x61,
+        0x62, 0x38, 0x39, 0x36, 0x35, 0x2d, 0x32, 0x63,
+        0x2d, 0x34, 0x39, 0x34, 0x33, 0x62, 0x37, 0x61,
+        0x37, 0x66, 0x37, 0x66, 0x38, 0x30, 0x22, 0x0d,
+        0x0a, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d,
+        0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x3a, 0x20,
+        0x62, 0x79, 0x74, 0x65, 0x73, 0x0d, 0x0a, 0x43,
+        0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c,
+        0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20, 0x34,
+        0x34, 0x0d, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
+        0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63,
+        0x6c, 0x6f, 0x73, 0x65, 0x0d, 0x0a, 0x43, 0x6f,
+        0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79,
+        0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74,
+        0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x0d, 0x0a, 0x58,
+        0x2d, 0x50, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x76,
+        0x6f, 0x69, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77,
+        0x73, 0x65, 0x72, 0x20, 0x62, 0x75, 0x67, 0x0d,
+        0x0a, 0x0d, 0x0a, 0x3c, 0x68, 0x74, 0x6d, 0x6c,
+        0x3e, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x3c,
+        0x68, 0x31, 0x3e, 0x49, 0x74, 0x20, 0x77, 0x6f,
+        0x72, 0x6b, 0x73, 0x21, 0x3c, 0x2f, 0x68, 0x31,
+        0x3e, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e,
+        0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e };
+    p->tcph->th_ack = htonl(88);
+    p->tcph->th_seq = htonl(1);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = sizeof(response);
+    p->payload = response;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_UNKNOWN ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list == NULL ||
+        ssn->client.seg_list->next == NULL ||
+        ssn->client.seg_list->next->next != NULL ||
+        ssn->server.seg_list == NULL ||
+        ssn->server.seg_list->next != NULL ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 7\n");
+        goto end;
+    }
+
+    /* response ack from request */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(88);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list == NULL ||
+        ssn->client.seg_list->next == NULL ||
+        ssn->client.seg_list->next->next != NULL ||
+        ssn->server.seg_list == NULL ||
+        ssn->server.seg_list->next != NULL ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 8\n");
+        goto end;
+    }
+
+    /* response - acking */
+    p->tcph->th_ack = htonl(88);
+    p->tcph->th_seq = htonl(328);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list == NULL ||
+        ssn->client.seg_list->next != NULL ||
+        ssn->server.seg_list == NULL ||
+        ssn->server.seg_list->next != NULL ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 9\n");
+        goto end;
+    }
+
+    /* response ack from request */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(88);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list == NULL ||
+        ssn->client.seg_list->next != NULL ||
+        ssn->server.seg_list == NULL ||
+        ssn->server.seg_list->next != NULL ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 10\n");
+        goto end;
+    }
+
+    /* response - acking the request again*/
+    p->tcph->th_ack = htonl(88);
+    p->tcph->th_seq = htonl(328);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list == NULL ||
+        ssn->client.seg_list->next != NULL ||
+        ssn->server.seg_list == NULL ||
+        ssn->server.seg_list->next != NULL ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 11\n");
+        goto end;
+    }
+
+    /*** New Request ***/
+
+    /* partial request */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(88);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request1);
+    p->payload = request1;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list == NULL ||
+        ssn->client.seg_list->next == NULL ||
+        ssn->client.seg_list->next->next != NULL ||
+        ssn->server.seg_list == NULL ||
+        ssn->server.seg_list->next != NULL ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 12\n");
+        goto end;
+    }
+
+
+    /* response ack against partial request */
+    p->tcph->th_ack = htonl(90);
+    p->tcph->th_seq = htonl(328);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list == NULL ||
+        ssn->client.seg_list->next == NULL ||
+        ssn->client.seg_list->next->next != NULL ||
+        ssn->server.seg_list == NULL ||
+        ssn->server.seg_list->next != NULL ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 13\n");
+        goto end;
+    }
+
+    /* complete request */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(90);
+    p->tcph->th_flags = TH_PUSH | TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = sizeof(request2);
+    p->payload = request2;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list == NULL ||
+        ssn->client.seg_list->next == NULL ||
+        ssn->client.seg_list->next->next == NULL ||
+        ssn->client.seg_list->next->next->next != NULL ||
+        ssn->server.seg_list == NULL ||
+        ssn->server.seg_list->next != NULL ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 14\n");
+        goto end;
+    }
+
+    /* response ack against second partial request */
+    p->tcph->th_ack = htonl(175);
+    p->tcph->th_seq = htonl(328);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list->next == NULL ||
+        ssn->client.seg_list->next->next == NULL ||
+        ssn->client.seg_list->next->next->next != NULL ||
+        ssn->server.seg_list == NULL ||
+        ssn->server.seg_list->next != NULL ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 15\n");
+        goto end;
+    }
+
+    if (ssn->toserver_smsg_head == NULL ||
+        ssn->toserver_smsg_head->next == NULL ||
+        ssn->toserver_smsg_head->next->next != NULL ||
+        ssn->toclient_smsg_head == NULL ||
+        ssn->toclient_smsg_head->next != NULL) {
+        printf("failure 16\n");
+        goto end;
+    }
+
+    StreamMsgReturnListToPool(ssn->toserver_smsg_head);
+    ssn->toserver_smsg_head = ssn->toserver_smsg_tail = NULL;
+    StreamMsgReturnListToPool(ssn->toclient_smsg_head);
+    ssn->toclient_smsg_head = ssn->toclient_smsg_tail = NULL;
+
+    /* response acking a request */
+    p->tcph->th_ack = htonl(175);
+    p->tcph->th_seq = htonl(328);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOCLIENT;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
+        goto end;
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list != NULL ||
+        ssn->server.seg_list == NULL ||
+        ssn->server.seg_list->next != NULL ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 15\n");
+        goto end;
+    }
+
+    /* request acking a response */
+    p->tcph->th_ack = htonl(328);
+    p->tcph->th_seq = htonl(175);
+    p->tcph->th_flags = TH_ACK;
+    p->flowflags = FLOW_PKT_TOSERVER;
+    p->payload_len = 0;
+    p->payload = NULL;
+    if (StreamTcpPacket(&tv, p, stt, &pq) == -1)
         goto end;
-    }
-
-    SCLogDebug("ssn.client.seg_list->flags %02x, seg %p", ssn.client.seg_list->flags, ssn.client.seg_list);
-
-    if (!(ssn.client.seg_list->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED)) {
-        printf("segment should have flags SEGMENTTCP_FLAG_APPLAYER_PROCESSED set (15): ");
+    if (!(ssn->server.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        !(ssn->client.flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) ||
+        f.alproto != ALPROTO_HTTP ||
+        f.alproto_ts != ALPROTO_HTTP ||
+        f.alproto_tc != ALPROTO_HTTP ||
+        f.data_al_so_far[0] != 0 ||
+        f.data_al_so_far[1] != 0 ||
+        f.flags & FLOW_NO_APPLAYER_INSPECTION ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOSERVER) || !FLOW_IS_PP_DONE(&f, STREAM_TOSERVER) ||
+        !FLOW_IS_PM_DONE(&f, STREAM_TOCLIENT) || FLOW_IS_PP_DONE(&f, STREAM_TOCLIENT) ||
+        ssn->client.seg_list != NULL ||
+        ssn->server.seg_list != NULL ||
+        ssn->data_first_seen_dir != 0x01) {
+        printf("failure 15\n");
         goto end;
     }
 
-    if (!(ssn.client.seg_list->flags & SEGMENTTCP_FLAG_RAW_PROCESSED)) {
-        printf("segment should have flags SEGMENTTCP_FLAG_RAW_PROCESSED set (16): ");
-        goto end;
-    }
 
     ret = 1;
 end:
-    StreamTcpReassembleFreeThreadCtx(ra_ctx);
+    StreamTcpThreadDeinit(&tv, (void *)stt);
+    StreamTcpSessionClear(p->flow->protoctx);
     StreamTcpFreeConfig(TRUE);
     SCFree(p);
-    SCMutexUnlock(&f->m);
-    UTHFreeFlow(f);
+    SCMutexUnlock(&f.m);
     return ret;
 }
 
@@ -6597,197 +6955,6 @@ end:
     return ret;
 }
 
-/**
- *  \test   Test to make sure we don't send more than one smsg from toserver to
- *          app layer  until the app layer protocol has not been detected. After
- *          protocol has been detected the processed segments should be returned
- *          to pool.
- *
- *  \retval On success it returns 1 and on failure 0.
- */
-
-static int StreamTcpReassembleTest41 (void) {
-    int ret = 0;
-    Packet *p = PacketGetFromAlloc();
-    if (unlikely(p == NULL))
-        return 0;
-    Flow *f = NULL;
-    TCPHdr tcph;
-    TcpSession ssn;
-    PacketQueue pq;
-    memset(&pq,0,sizeof(PacketQueue));
-    memset(&tcph, 0, sizeof (TCPHdr));
-    memset(&ssn, 0, sizeof(TcpSession));
-    ThreadVars tv;
-    memset(&tv, 0, sizeof (ThreadVars));
-
-    StreamTcpInitConfig(TRUE);
-    TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx();
-
-    uint8_t httpbuf1[] = "GET / HTTP/1.0\r\nUser-Agent: Victor/1.0"
-                         "W2dyb3VwMV0NCnBob25lMT1wMDB3ODgyMTMxMzAyMTINCmxvZ2lu"
-                         "MT0NCnBhc3N3b3JkMT0NCnBob25lMj1wMDB3ODgyMTMxMzAyMTIN"
-                         "CmxvZ2luMj0NCnBhc3N3b3JkMj0NCnBob25lMz0NCmxvZ2luMz0N"
-                         "CnBhc3N3b3JkMz0NCnBob25lND0NCmxvZ2luND0NCnBhc3N3b3Jk"
-                         "ND0NCnBob25lNT0NCmxvZ2luNT0NCnBhc3N3b3JkNT0NCnBob25l"
-                         "Nj0NCmxvZ2luNj0NCnBhc3N3b3JkNj0NCmNhbGxfdGltZTE9MzIN"
-                         "CmNhbGxfdGltZTI9MjMyDQpkYXlfbGltaXQ9NQ0KbW9udGhfbGlt"
-                         "aXQ9MTUNCltncm91cDJdDQpwaG9uZTE9DQpsb2dpbjE9DQpwYXNz"
-                         "d29yZDE9DQpwaG9uZTI9DQpsb2dpbjI9DQpwYXNzd29yZDI9DQpw"
-                         "aG9uZT";
-    uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
-
-    uint8_t httpbuf3[] = "psb2dpbjM9DQpwYXNzd29yZDM9DQpwaG9uZTQ9DQps"
-                         "b2dpbjQ9DQpwYXNzd29yZDQ9DQpwaG9uZTU9DQpsb2dpbjU9DQpw"
-                         "YXNzd29yZDU9DQpwaG9uZTY9DQpsb2dpbjY9DQpwYXNzd29yZDY9"
-                         "DQpjYWxsX3RpbWUxPQ0KY2FsbF90aW1lMj0NCmRheV9saW1pdD0N"
-                         "\r\n\r\n";
-    uint32_t httplen3 = sizeof(httpbuf3) - 1; /* minus the \0 */
-
-    uint8_t httpbuf2[] = "HTTP/1.0 200 OK\r\nServer: VictorServer/1.0\r\n\r\n";
-    uint32_t httplen2 = sizeof(httpbuf2) - 1; /* minus the \0 */
-
-    StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 100);
-    StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 500);
-
-    ssn.server.ra_raw_base_seq = ssn.server.ra_app_base_seq = 9;
-    ssn.server.isn = 9;
-    ssn.server.last_ack = 600;
-    ssn.client.ra_raw_base_seq = ssn.client.ra_app_base_seq = 9;
-    ssn.client.isn = 9;
-    ssn.client.last_ack = 600;
-
-    f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 200, 220);
-    if (f == NULL)
-        goto end;
-    f->protoctx = &ssn;
-    p->flow = f;
-
-    tcph.th_win = htons(5480);
-    tcph.th_seq = htonl(10);
-    tcph.th_ack = htonl(20);
-    tcph.th_flags = TH_ACK|TH_PUSH;
-    p->tcph = &tcph;
-    p->flowflags = FLOW_PKT_TOCLIENT;
-
-    p->payload = httpbuf2;
-    p->payload_len = httplen2;
-    ssn.state = TCP_ESTABLISHED;
-
-    TcpStream *s = NULL;
-    s = &ssn.server;
-
-    SCMutexLock(&f->m);
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet: ");
-        goto end;
-    }
-
-    /* Check if we have stream smsgs in queue */
-    if (ra_ctx->stream_q->len > 0) {
-        printf("there shouldn't be any stream smsgs in the queue: ");
-        goto end;
-    }
-
-    p->flowflags = FLOW_PKT_TOSERVER;
-    p->payload = httpbuf1;
-    p->payload_len = httplen1;
-    tcph.th_seq = htonl(10);
-    tcph.th_ack = htonl(55);
-    s = &ssn.client;
-
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet: ");
-        goto end;
-    }
-
-    p->flowflags = FLOW_PKT_TOSERVER;
-    p->payload = httpbuf3;
-    p->payload_len = httplen3;
-    tcph.th_seq = htonl(522);
-    tcph.th_ack = htonl(100);
-    s = &ssn.client;
-
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet: ");
-        goto end;
-    }
-
-    /* Check if we have stream smsgs in queue */
-    if (ra_ctx->stream_q->len == 0) {
-        printf("there should be stream smsgs in the queue: ");
-        goto end;
-    }
-
-    if (StreamTcpReassembleProcessAppLayer(ra_ctx) < 0) {
-        printf("failed in processing stream smsgs: ");
-        goto end;
-    }
-
-    p->flowflags = FLOW_PKT_TOCLIENT;
-    p->payload = httpbuf2;
-    p->payload_len = httplen2;
-    tcph.th_seq = htonl(55);
-    tcph.th_ack = htonl(522);
-    s = &ssn.server;
-
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet: ");
-        goto end;
-    }
-
-    /* Check if we have stream smsgs in queue */
-    if (ra_ctx->stream_q->len == 0) {
-        printf("there should be a stream smsgs in the queue: ");
-        goto end;
-    /* Process stream smsgs we may have in queue */
-    } else if (ra_ctx->stream_q->len > 1) {
-        printf("there should be only one stream smsgs in the queue: ");
-        goto end;
-    } else if (StreamTcpReassembleProcessAppLayer(ra_ctx) < 0) {
-        printf("failed in processing stream smsgs: ");
-        goto end;
-    }
-
-    p->flowflags = FLOW_PKT_TOCLIENT;
-    p->payload = httpbuf2;
-    p->payload_len = httplen2;
-    tcph.th_seq = htonl(100);
-    tcph.th_ack = htonl(522);
-    s = &ssn.server;
-
-    if (StreamTcpReassembleHandleSegment(&tv, ra_ctx, &ssn, s, p, &pq) == -1) {
-        printf("failed in segments reassembly, while processing toserver packet: ");
-        goto end;
-    }
-
-    /* check if the segment in the list is flagged or not */
-    if (ssn.client.seg_list == NULL) {
-        printf("segment list should not be empty: ");
-        goto end;
-    }
-
-    /* last_ack is in the middle of this segment */
-    if ((ssn.client.seg_list->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED)) {
-        printf("segment should not have flags SEGMENTTCP_FLAG_APPLAYER_PROCESSED set: ");
-        goto end;
-    }
-
-    if (!(ssn.client.seg_list->flags & SEGMENTTCP_FLAG_RAW_PROCESSED)) {
-        printf("segment should have flags SEGMENTTCP_FLAG_RAW_PROCESSED set: ");
-        goto end;
-    }
-
-    ret = 1;
-end:
-    StreamTcpReassembleFreeThreadCtx(ra_ctx);
-    StreamTcpFreeConfig(TRUE);
-    SCFree(p);
-    SCMutexUnlock(&f->m);
-    UTHFreeFlow(f);
-    return ret;
-}
-
 /**
  *  \retval On success it returns 1 and on failure 0.
  */
@@ -8713,7 +8880,6 @@ void StreamTcpReassembleRegisterTests(void) {
     UtRegisterTest("StreamTcpReassembleTest38 -- app proto test", StreamTcpReassembleTest38, 1);
     UtRegisterTest("StreamTcpReassembleTest39 -- app proto test", StreamTcpReassembleTest39, 1);
     UtRegisterTest("StreamTcpReassembleTest40 -- app proto test", StreamTcpReassembleTest40, 1);
-    UtRegisterTest("StreamTcpReassembleTest41 -- app proto test", StreamTcpReassembleTest41, 1);
     UtRegisterTest("StreamTcpReassembleTest43 -- min smsg size test", StreamTcpReassembleTest43, 1);
     UtRegisterTest("StreamTcpReassembleTest44 -- Memcap Test", StreamTcpReassembleTest44, 1);
     UtRegisterTest("StreamTcpReassembleTest45 -- Depth Test", StreamTcpReassembleTest45, 1);
index d3e54b5cb56998eea88ec78d4bf70ba8faa66879..47a06c1891dfe30e8d70602208c6574fd79d2ee4 100644 (file)
@@ -72,6 +72,9 @@ void StreamTcpReassembleFree(char);
 void StreamTcpReassembleRegisterTests(void);
 TcpReassemblyThreadCtx *StreamTcpReassembleInitThreadCtx(void);
 void StreamTcpReassembleFreeThreadCtx(TcpReassemblyThreadCtx *);
+int StreamTcpReassembleAppLayer (ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
+                                 TcpSession *ssn, TcpStream *stream,
+                                 Packet *p);
 int StreamTcpReassembleProcessAppLayer(TcpReassemblyThreadCtx *);
 
 void StreamTcpCreateTestPacket(uint8_t *, uint8_t, uint8_t, uint8_t);
index 12d23f2830bd6069b19596e61ef7cf2b77acde97..db3ae987fbfa383e0573996c4b57e4f88778df35 100644 (file)
@@ -4139,8 +4139,8 @@ static int StreamTcpPacketIsWindowUpdate(TcpSession *ssn, Packet *p) {
 }
 
 /* flow is and stays locked */
-static int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
-                            PacketQueue *pq)
+int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
+                     PacketQueue *pq)
 {
     SCEnter();
 
index 1667fb116185855d38b5f4ffbe43037bef051e61..c9f38fa6a1c7f950ad325e701f26f84b577d878a 100644 (file)
@@ -202,5 +202,11 @@ static inline int StreamHasUnprocessedSegments(TcpSession *ssn, int direction)
     }
 }
 
+TmEcode StreamTcpThreadInit(ThreadVars *, void *, void **);
+TmEcode StreamTcpThreadDeinit(ThreadVars *tv, void *data);
+int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
+                     PacketQueue *pq);
+void StreamTcpSessionClear(void *ssnptr);
+
 #endif /* __STREAM_TCP_H__ */