/** Parse http header response line 1 */ static err_t http_parse_response_status(struct pbuf *p, u16_t *http_version, u16_t *http_status, u16_t *http_status_str_offset) { u16_t end1 = pbuf_memfind(p, "\r\n", 2, 0); if (end1 != 0xFFFF) { /* get parts of first line */ u16_t space1, space2; space1 = pbuf_memfind(p, " ", 1, 0); if (space1 != 0xFFFF) { if ((pbuf_memcmp(p, 0, "HTTP/", 5) == 0) && (pbuf_get_at(p, 6) == '.')) { char status_num[10]; size_t status_num_len; /* parse http version */ u16_t version = pbuf_get_at(p, 5) - '0'; version <<= 8; version |= pbuf_get_at(p, 7) - '0'; *http_version = version; /* parse http status number */ space2 = pbuf_memfind(p, " ", 1, space1 + 1); if (space2 != 0xFFFF) { *http_status_str_offset = space2 + 1; status_num_len = space2 - space1 - 1; } else { status_num_len = end1 - space1 - 1; } memset(status_num, 0, sizeof(status_num)); if (pbuf_copy_partial(p, status_num, (u16_t)status_num_len, space1 + 1) == status_num_len) { int status = atoi(status_num); if ((status > 0) && (status <= 0xFFFF)) { *http_status = (u16_t)status; return ERR_OK; } } } } } return ERR_VAL; }
/** Receive data on an iperf tcp session */ static err_t lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { u16_t tot_len; u32_t packet_idx; struct pbuf* q; lwiperf_state_tcp_t* conn = (lwiperf_state_tcp_t*)arg; LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); LWIP_UNUSED_ARG(tpcb); if (err != ERR_OK) { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); return ERR_OK; } if (p == NULL) { /* connection closed -> test done */ if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) { /* client requested transmission after end of test */ lwiperf_tx_start(conn); } lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER); return ERR_OK; } tot_len = p->tot_len; conn->poll_count = 0; if ((!conn->have_settings_buf) || ((conn->bytes_transferred -24) % (1024*128) == 0)) { /* wait for 24-byte header */ if (p->tot_len < sizeof(lwiperf_settings_t)) { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); pbuf_free(p); return ERR_VAL; } if (!conn->have_settings_buf) { if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); pbuf_free(p); return ERR_VAL; } conn->have_settings_buf = 1; if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) == PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST|LWIPERF_FLAGS_ANSWER_NOW)) { /* client requested parallel transmission test */ err_t err2 = lwiperf_tx_start(conn); if (err2 != ERR_OK) { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR); pbuf_free(p); return err2; } } } else { if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); pbuf_free(p); return ERR_VAL; } } conn->bytes_transferred += sizeof(lwiperf_settings_t); if(conn->bytes_transferred <= 24) { conn->time_started = sys_now(); tcp_recved(tpcb, p->tot_len); pbuf_free(p); return ERR_OK; } conn->next_num = 4; /* 24 bytes received... */ err = pbuf_header(p, -24); LWIP_ASSERT("pbuf_header failed", err == ERR_OK); } packet_idx = 0; for (q = p; q != NULL; q = q->next) { #if LWIPERF_CHECK_RX_DATA const u8_t* payload = (const u8_t*)q->payload; u16_t i; for (i = 0; i < q->len; i++) { u8_t val = payload[i]; u8_t num = val - '0'; if (num == conn->next_num) { conn->next_num++; if (conn->next_num == 10) { conn->next_num = 0; } } else { lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); pbuf_free(p); return ERR_VAL; } } packet_idx += i; #else packet_idx += q->len; #endif } LWIP_ASSERT("count mismatch", packet_idx == p->tot_len); conn->bytes_transferred += packet_idx; tcp_recved(tpcb, tot_len); pbuf_free(p); return ERR_OK; }