45ccea27aae6dbe4c4c03d30b5c395c4c1e973a5
[deb_shairplay.git] / src / lib / http_response.c
1 /**
2 * Copyright (C) 2011-2012 Juho Vähä-Herttua
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <assert.h>
19
20 #include "http_response.h"
21
22 struct http_response_s {
23 int complete;
24
25 char *data;
26 int data_size;
27 int data_length;
28 };
29
30
31 static void
32 http_response_add_data(http_response_t *response, const char *data, int datalen)
33 {
34 int newdatasize;
35
36 assert(response);
37 assert(data);
38 assert(datalen > 0);
39
40 newdatasize = response->data_size;
41 while (response->data_size+datalen > newdatasize) {
42 newdatasize *= 2;
43 }
44 if (newdatasize != response->data_size) {
45 response->data = realloc(response->data, newdatasize);
46 assert(response->data);
47 }
48 memcpy(response->data+response->data_length, data, datalen);
49 response->data_length += datalen;
50 }
51
52 http_response_t *
53 http_response_init(const char *protocol, int code, const char *message)
54 {
55 http_response_t *response;
56 char codestr[4];
57
58 assert(code >= 100 && code < 1000);
59
60 /* Convert code into string */
61 memset(codestr, 0, sizeof(codestr));
62 snprintf(codestr, sizeof(codestr), "%u", code);
63
64 response = calloc(1, sizeof(http_response_t));
65 if (!response) {
66 return NULL;
67 }
68
69 /* Allocate response data */
70 response->data_size = 1024;
71 response->data = malloc(response->data_size);
72 if (!response->data) {
73 free(response);
74 return NULL;
75 }
76
77 /* Add first line of response to the data array */
78 http_response_add_data(response, protocol, strlen(protocol));
79 http_response_add_data(response, " ", 1);
80 http_response_add_data(response, codestr, strlen(codestr));
81 http_response_add_data(response, " ", 1);
82 http_response_add_data(response, message, strlen(message));
83 http_response_add_data(response, "\r\n", 2);
84
85 return response;
86 }
87
88 void
89 http_response_destroy(http_response_t *response)
90 {
91 if (response) {
92 free(response->data);
93 free(response);
94 }
95 }
96
97 void
98 http_response_add_header(http_response_t *response, const char *name, const char *value)
99 {
100 assert(response);
101 assert(name);
102 assert(value);
103
104 http_response_add_data(response, name, strlen(name));
105 http_response_add_data(response, ": ", 2);
106 http_response_add_data(response, value, strlen(value));
107 http_response_add_data(response, "\r\n", 2);
108 }
109
110 void
111 http_response_finish(http_response_t *response, const char *data, int datalen)
112 {
113 assert(response);
114 assert(datalen==0 || (data && datalen > 0));
115
116 if (data && datalen > 0) {
117 const char *hdrname = "Content-Length";
118 char hdrvalue[16];
119
120 memset(hdrvalue, 0, sizeof(hdrvalue));
121 snprintf(hdrvalue, sizeof(hdrvalue)-1, "%d", datalen);
122
123 /* Add Content-Length header first */
124 http_response_add_data(response, hdrname, strlen(hdrname));
125 http_response_add_data(response, ": ", 2);
126 http_response_add_data(response, hdrvalue, strlen(hdrvalue));
127 http_response_add_data(response, "\r\n\r\n", 4);
128
129 /* Add data to the end of response */
130 http_response_add_data(response, data, datalen);
131 } else {
132 /* Add extra end of line after headers */
133 http_response_add_data(response, "\r\n", 2);
134 }
135 response->complete = 1;
136 }
137
138 const char *
139 http_response_get_data(http_response_t *response, int *datalen)
140 {
141 assert(response);
142 assert(datalen);
143 assert(response->complete);
144
145 *datalen = response->data_length;
146 return response->data;
147 }