| 738 | } |
| 739 | |
| 740 | void cbm_http_reply_buf(cbm_http_conn_t *c, int status, const char *extra_headers, const void *data, |
| 741 | size_t len) { |
| 742 | if (!c) |
| 743 | return; |
| 744 | atomic_store_explicit(&c->response_started, true, memory_order_release); |
| 745 | c->response_status = status; |
| 746 | c->response_bytes = len; |
| 747 | char head[1024]; |
| 748 | int hn = snprintf(head, sizeof(head), |
| 749 | "HTTP/1.1 %d %s\r\n" |
| 750 | "%s" |
| 751 | "Content-Length: %zu\r\n" |
| 752 | "Connection: close\r\n" |
| 753 | "\r\n", |
| 754 | status, status_reason(status), extra_headers ? extra_headers : "", len); |
| 755 | if (hn < 0 || hn >= (int)sizeof(head)) |
| 756 | return; /* oversized extra_headers — drop the response, conn closes */ |
| 757 | int64_t deadline = now_ms() + c->send_deadline_ms; |
| 758 | if (send_all(c, head, (size_t)hn, deadline) != 0) |
| 759 | return; |
| 760 | if (len > 0) |
| 761 | (void)send_all(c, data, len, deadline); |
| 762 | } |
| 763 | |
| 764 | void cbm_http_replyf(cbm_http_conn_t *c, int status, const char *extra_headers, const char *fmt, |
| 765 | ...) { |