Add some compatibility defines to dnssd.c.
[deb_shairplay.git] / src / lib / http_response.c
CommitLineData
23e7e3ae
JVH
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
2340bcd3
JVH
15#include <stdlib.h>
16#include <stdio.h>
17#include <string.h>
18#include <assert.h>
19
20#include "http_response.h"
566c9bf8 21#include "compat.h"
2340bcd3
JVH
22
23struct http_response_s {
24 int complete;
c5f65268 25 int disconnect;
2340bcd3
JVH
26
27 char *data;
28 int data_size;
29 int data_length;
30};
31
32
33static void
34http_response_add_data(http_response_t *response, const char *data, int datalen)
35{
36 int newdatasize;
37
38 assert(response);
39 assert(data);
40 assert(datalen > 0);
41
42 newdatasize = response->data_size;
43 while (response->data_size+datalen > newdatasize) {
44 newdatasize *= 2;
45 }
46 if (newdatasize != response->data_size) {
47 response->data = realloc(response->data, newdatasize);
48 assert(response->data);
49 }
50 memcpy(response->data+response->data_length, data, datalen);
51 response->data_length += datalen;
52}
53
54http_response_t *
55http_response_init(const char *protocol, int code, const char *message)
56{
57 http_response_t *response;
58 char codestr[4];
59
60 assert(code >= 100 && code < 1000);
61
62 /* Convert code into string */
63 memset(codestr, 0, sizeof(codestr));
64 snprintf(codestr, sizeof(codestr), "%u", code);
65
66 response = calloc(1, sizeof(http_response_t));
67 if (!response) {
68 return NULL;
69 }
70
71 /* Allocate response data */
72 response->data_size = 1024;
73 response->data = malloc(response->data_size);
74 if (!response->data) {
75 free(response);
76 return NULL;
77 }
78
79 /* Add first line of response to the data array */
80 http_response_add_data(response, protocol, strlen(protocol));
81 http_response_add_data(response, " ", 1);
82 http_response_add_data(response, codestr, strlen(codestr));
83 http_response_add_data(response, " ", 1);
84 http_response_add_data(response, message, strlen(message));
85 http_response_add_data(response, "\r\n", 2);
86
87 return response;
88}
89
90void
91http_response_destroy(http_response_t *response)
92{
93 if (response) {
94 free(response->data);
95 free(response);
96 }
97}
98
99void
100http_response_add_header(http_response_t *response, const char *name, const char *value)
101{
102 assert(response);
103 assert(name);
104 assert(value);
105
106 http_response_add_data(response, name, strlen(name));
107 http_response_add_data(response, ": ", 2);
108 http_response_add_data(response, value, strlen(value));
109 http_response_add_data(response, "\r\n", 2);
110}
111
112void
113http_response_finish(http_response_t *response, const char *data, int datalen)
114{
115 assert(response);
116 assert(datalen==0 || (data && datalen > 0));
117
118 if (data && datalen > 0) {
119 const char *hdrname = "Content-Length";
120 char hdrvalue[16];
121
122 memset(hdrvalue, 0, sizeof(hdrvalue));
123 snprintf(hdrvalue, sizeof(hdrvalue)-1, "%d", datalen);
124
125 /* Add Content-Length header first */
126 http_response_add_data(response, hdrname, strlen(hdrname));
127 http_response_add_data(response, ": ", 2);
128 http_response_add_data(response, hdrvalue, strlen(hdrvalue));
129 http_response_add_data(response, "\r\n\r\n", 4);
130
131 /* Add data to the end of response */
132 http_response_add_data(response, data, datalen);
133 } else {
134 /* Add extra end of line after headers */
135 http_response_add_data(response, "\r\n", 2);
136 }
137 response->complete = 1;
138}
139
c5f65268
JVH
140void
141http_response_set_disconnect(http_response_t *response, int disconnect)
142{
143 assert(response);
144
145 response->disconnect = !!disconnect;
146}
147
148int
149http_response_get_disconnect(http_response_t *response)
150{
151 assert(response);
152
153 return response->disconnect;
154}
155
2340bcd3
JVH
156const char *
157http_response_get_data(http_response_t *response, int *datalen)
158{
159 assert(response);
160 assert(datalen);
161 assert(response->complete);
162
163 *datalen = response->data_length;
164 return response->data;
165}