/* SPDX-License-Identifier: GPL-3.0-or-later */ /* Copyright 2022 Ivan Polyakov */ #include "response.h" #include #include #include static size_t calc_res_status_sz(const rpd_res *res); static size_t calc_res_headers_sz(const rpd_keyval *res); void rpd_res_init(rpd_res *dest) { dest->status = rpd_res_st_ok; dest->body = NULL; rpd_keyval_init(&dest->headers, 5); dest->headers.unique = 0; } int rpd_res_headers_str(char **dest, const rpd_res *src) { size_t size, i = 0; char *ptr; size = calc_res_headers_sz(&src->headers); *dest = (char *) malloc(sizeof(char) * size); if (!*dest) { perror("malloc"); return 1; } ptr = *dest; while (i < src->headers.size) { ptr += sprintf( ptr, "%s: %s\r\n", src->headers.items[i].key, src->headers.items[i].val); i++; } return 0; } int rpd_res_str(char **dest, const rpd_res *res) { size_t headers_size, size; char *ptr, *headers; size = headers_size = calc_res_headers_sz(&res->headers); size += calc_res_status_sz(res); if (res->body) size += 2 + strlen(res->body); *dest = (char *) malloc(sizeof(char) * size); if (!*dest) { perror("malloc"); return 1; } /* header */ ptr = *dest; ptr += sprintf(ptr, "Status: %d\r\n", res->status); if (rpd_res_headers_str(&headers, res)) { return 1; } memcpy(ptr, headers, headers_size); free(headers); ptr += headers_size; memcpy(ptr, "\r\n", 2); ptr += 2; /* body */ if (res->body) { int bodylen = strlen(res->body); memcpy(ptr, res->body, bodylen); ptr += bodylen; } return 0; } static size_t calc_res_status_sz(const rpd_res *res) { size_t size = 0; size += strlen("Status: \r\n"); size += 3; /* plus status code */ return size; } static size_t calc_res_headers_sz(const rpd_keyval *headers) { size_t size = 0, i = 0; while (i < headers->size) { size += strlen(headers->items[i].key); size += 2; /* plus ": " */ size += strlen(headers->items[i].val); size += 2; /* plus CRLF */ i++; } return size; } void rpd_res_cleanup(rpd_res *res) { res->status = rpd_res_st_ok; if (res->body) { free(res->body); res->body = NULL; } if (res->headers.capacity) { rpd_keyval_cleanup(&res->headers); } }