+ if (hc->rx_buf_offset >= vec_len (hc->rx_buf))
+ {
+ vec_reset_length (hc->rx_buf);
+ hc->rx_buf_offset = 0;
+ }
+
+ app_wrk = app_worker_get_if_valid (as->app_wrk_index);
+ ASSERT (app_wrk);
+
+ app_worker_rx_notify (app_wrk, as);
+ return 1;
+}
+
+static http_sm_result_t
+state_cln_recv_more_data (http_conn_t *hc, transport_send_params_t *sp)
+{
+ session_t *as;
+ u32 max_deq;
+ session_t *ts;
+ int n_read, rv;
+
+ as = session_get_from_handle (hc->h_pa_session_handle);
+ ts = session_get_from_handle (hc->h_tc_session_handle);
+
+ u32 dlen = vec_len (hc->rx_buf) - hc->rx_buf_offset;
+ if (dlen)
+ {
+ rv = cln_drain_rx_buf (hc, ts, as);
+ if (rv < 0)
+ {
+ clib_warning ("drain rx error!");
+ return HTTP_SM_ERROR;
+ }
+ goto maybe_reschedule;
+ }
+
+ if (hc->to_recv == 0)
+ {
+ ASSERT (vec_len (hc->rx_buf) == 0);
+ ASSERT (hc->rx_buf_offset == 0);
+ hc->http_state = HTTP_STATE_WAIT_APP;
+ return HTTP_SM_STOP;
+ }
+
+ max_deq = svm_fifo_max_dequeue (ts->rx_fifo);
+ if (max_deq == 0)
+ return HTTP_SM_STOP;
+
+ ASSERT (vec_len (hc->rx_buf) == 0);
+ ASSERT (hc->rx_buf_offset == 0);
+
+ vec_validate (hc->rx_buf, max_deq - 1);
+ n_read = svm_fifo_dequeue (ts->rx_fifo, max_deq, hc->rx_buf);
+ ASSERT (n_read == max_deq);
+
+ if (svm_fifo_is_empty (ts->rx_fifo))
+ svm_fifo_unset_event (ts->rx_fifo);
+
+ hc->to_recv -= n_read;
+ vec_set_len (hc->rx_buf, max_deq);
+
+maybe_reschedule:
+ if (hc->rx_buf_offset < vec_len (hc->rx_buf) ||
+ svm_fifo_max_dequeue_cons (ts->rx_fifo))
+ {
+ /* TODO is the flag really needed? */
+ if (svm_fifo_set_event (ts->rx_fifo))
+ session_enqueue_notify (ts);
+ }
+ return HTTP_SM_CONTINUE;
+}
+
+static http_sm_result_t
+state_cln_wait_app (http_conn_t *hc, transport_send_params_t *sp)
+{
+ session_t *as;
+ http_msg_t msg;
+ http_status_code_t ec;
+ u8 *buf = 0, *request;
+ u32 offset;
+ int rv;
+
+ as = session_get_from_handle (hc->h_pa_session_handle);
+ rv = svm_fifo_dequeue (as->tx_fifo, sizeof (msg), (u8 *) &msg);
+ ASSERT (rv == sizeof (msg));
+ if (msg.type != HTTP_MSG_REQUEST || msg.data.type > HTTP_MSG_DATA_PTR)
+ {
+ clib_warning ("unexpected msg type from app %u", msg.type);
+ ec = HTTP_STATUS_INTERNAL_ERROR;
+ goto error;
+ }
+
+ vec_validate (buf, msg.data.len - 1);
+ rv = svm_fifo_dequeue (as->tx_fifo, msg.data.len, buf);
+ ASSERT (rv == msg.data.len);
+
+ request = format (0, http_request_template, buf);
+ offset = send_data (hc, request, vec_len (request), 0);
+ if (offset != vec_len (request))
+ {
+ clib_warning ("sending request failed!");
+ ec = HTTP_STATUS_INTERNAL_ERROR;
+ goto error;
+ }
+
+ hc->http_state = HTTP_STATE_WAIT_METHOD;
+
+ vec_free (buf);
+ vec_free (request);
+
+ return HTTP_SM_CONTINUE;
+
+error:
+ send_error (hc, ec);
+ session_transport_closing_notify (&hc->connection);
+ http_disconnect_transport (hc);
+ return HTTP_SM_STOP;
+}
+
+typedef http_sm_result_t (*http_sm_handler) (http_conn_t *,
+ transport_send_params_t *sp);
+
+static http_sm_handler srv_state_funcs[HTTP_N_STATES] = {