TRACE_ENTER(FCGI_EV_TX_RECORD|FCGI_EV_TX_PARAMS, fconn->conn, fstrm, htx);
- memset(¶ms, 0, sizeof(params));
- params.p = get_trash_chunk();
-
mbuf = br_tail(fconn->mbuf);
retry:
if (!fcgi_get_buf(fconn, mbuf)) {
fcgi_set_record_id(outbuf.area, fstrm->id);
outbuf.data = FCGI_RECORD_HEADER_SZ;
- blk = htx_get_head_blk(htx);
- while (blk) {
+ memset(¶ms, 0, sizeof(params));
+ params.p = get_trash_chunk();
+
+ for (blk = htx_get_head_blk(htx); blk; blk = htx_get_next_blk(htx, blk)) {
enum htx_blk_type type;
- uint32_t size = htx_get_blksz(blk);
struct fcgi_param p;
type = htx_get_blk_type(blk);
if (!fcgi_encode_param(&outbuf, &p)) {
if (b_space_wraps(mbuf))
goto realign_again;
- if (outbuf.data == FCGI_RECORD_HEADER_SZ)
- goto full;
- goto done;
+ goto full;
}
break;
if (!fcgi_encode_param(&outbuf, &p)) {
if (b_space_wraps(mbuf))
goto realign_again;
- if (outbuf.data == FCGI_RECORD_HEADER_SZ)
- goto full;
+ goto full;
}
TRACE_STATE("add server name header", FCGI_EV_TX_RECORD|FCGI_EV_TX_PARAMS, fconn->conn, fstrm);
}
default:
break;
}
- total += size;
- blk = htx_remove_blk(htx, blk);
}
done:
!fcgi_encode_default_param(fconn, fstrm, ¶ms, &outbuf, FCGI_SP_CONT_LEN) ||
!fcgi_encode_default_param(fconn, fstrm, ¶ms, &outbuf, FCGI_SP_SRV_SOFT) ||
!fcgi_encode_default_param(fconn, fstrm, ¶ms, &outbuf, FCGI_SP_HTTPS)) {
- TRACE_ERROR("error encoding default params", FCGI_EV_TX_RECORD|FCGI_EV_STRM_ERR, fconn->conn, fstrm);
- goto error;
+ if (b_space_wraps(mbuf))
+ goto realign_again;
+ goto full;
}
/* update the record's size */
fcgi_set_record_size(outbuf.area, outbuf.data - FCGI_RECORD_HEADER_SZ);
b_add(mbuf, outbuf.data);
+ /* remove all header blocks including the EOH and compute the
+ * corresponding size.
+ */
+ blk = htx_get_head_blk(htx);
+ while (blk) {
+ total += htx_get_blksz(blk);
+ blk = htx_remove_blk(htx, blk);
+ /* The removed block is the EOH */
+ if (htx_get_blk_type(blk) == HTX_BLK_EOH)
+ break;
+ }
+
end:
TRACE_LEAVE(FCGI_EV_TX_RECORD|FCGI_EV_TX_PARAMS, fconn->conn, fstrm, htx, (size_t[]){total});
return total;
full:
+ if (b_size(&outbuf) == b_size(mbuf) || b_size(&outbuf) == 0xFFFF + FCGI_RECORD_HEADER_SZ) {
+ TRACE_ERROR("Request too large to be sent", FCGI_EV_TX_RECORD|FCGI_EV_STRM_ERR, fconn->conn, fstrm);
+ goto error;
+ }
if ((mbuf = br_tail_add(fconn->mbuf)) != NULL)
goto retry;
fconn->flags |= FCGI_CF_MUX_MFULL;
fstrm->flags |= FCGI_SF_BLK_MROOM;
TRACE_STATE("mbuf ring full", FCGI_EV_TX_RECORD|FCGI_EV_FSTRM_BLK|FCGI_EV_FCONN_BLK, fconn->conn, fstrm);
- if (total)
- goto error;
goto end;
error: