1 /* Interface for HTTP functions
2  *
3  * Copyright (C) 2003-2004  Narcis Ilisei <inarcis2002@hotpop.com>
4  * Copyright (C) 2010-2021  Joachim Wiberg <troglobit@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, visit the Free Software Foundation
18  * website at http://www.gnu.org/licenses/gpl-2.0.html or write to the
19  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include <string.h>
24 
25 #include "ssl.h"
26 #include "http.h"
27 #include "error.h"
28 
http_construct(http_t * client)29 int http_construct(http_t *client)
30 {
31 	ASSERT(client);
32 
33 	DO(tcp_construct(&client->tcp));
34 
35 	memset((char *)client + sizeof(client->tcp), 0, sizeof(*client) - sizeof(client->tcp));
36 	client->initialized = 0;
37 
38 	return 0;
39 }
40 
http_destruct(http_t * client,int num)41 int http_destruct(http_t *client, int num)
42 {
43 	int i = 0, rv = 0;
44 
45 	while (i < num)
46 		rv = tcp_destruct(&client[i++].tcp);
47 
48 	return rv;
49 }
50 
local_set_params(http_t * client)51 static int local_set_params(http_t *client)
52 {
53 	int timeout = 0;
54 	int port = 0;
55 
56 	http_get_remote_timeout(client, &timeout);
57 	if (timeout == 0)
58 		http_set_remote_timeout(client, HTTP_DEFAULT_TIMEOUT);
59 
60 	http_get_port(client, &port);
61 	if (port == 0)
62 		http_set_port(client, HTTP_DEFAULT_PORT);
63 
64 	return 0;
65 }
66 
http_init(http_t * client,char * msg)67 int http_init(http_t *client, char *msg)
68 {
69 	int rc = 0;
70 
71 	do {
72 		TRY(local_set_params(client));
73 		TRY(ssl_open(client, msg));
74 	}
75 	while (0);
76 
77 	if (rc) {
78 		http_exit(client);
79 		return rc;
80 	}
81 
82 	client->initialized = 1;
83 
84 	return 0;
85 }
86 
http_exit(http_t * client)87 int http_exit(http_t *client)
88 {
89 	ASSERT(client);
90 
91 	if (!client->initialized)
92 		return 0;
93 
94 	client->initialized = 0;
95 	return ssl_close(client);
96 }
97 
http_response_parse(http_trans_t * trans)98 static void http_response_parse(http_trans_t *trans)
99 {
100 	char *body;
101 	char *rsp = trans->rsp_body = trans->rsp;
102 	int status = trans->status = 0;
103 	const char sep[] = "\r\n\r\n";
104 
105 	memset(trans->status_desc, 0, sizeof(trans->status_desc));
106 
107 	if (rsp != NULL && (body = strstr(rsp, sep)) != NULL) {
108 		body += strlen(sep);
109 		trans->rsp_body = body;
110 	}
111 
112 	/*
113 	 * %*c         : HTTP/1.0, 1.1 etc, discard read value
114 	 * %4d         : HTTP status code, e.g. 200
115 	 * %255[^\r\n] : HTTP status text, e.g. OK -- Reads max 255 bytes, including \0, not \r or \n
116 	 */
117 	if (sscanf(trans->rsp, "HTTP/1.%*c %4d %255[^\r\n]", &status, trans->status_desc) == 2)
118 		trans->status = status;
119 }
120 
http_transaction(http_t * client,http_trans_t * trans)121 int http_transaction(http_t *client, http_trans_t *trans)
122 {
123 	int rc = 0;
124 
125 	ASSERT(client);
126 	ASSERT(trans);
127 
128 	if (!client->initialized)
129 		return RC_HTTP_OBJECT_NOT_INITIALIZED;
130 
131 	trans->rsp_len = 0;
132 	do {
133 		TRY(ssl_send(client, trans->req, trans->req_len));
134 		TRY(ssl_recv(client, trans->rsp, trans->max_rsp_len, &trans->rsp_len));
135 	}
136 	while (0);
137 
138 	trans->rsp[trans->rsp_len] = 0;
139 	http_response_parse(trans);
140 
141 	return rc;
142 }
143 
http_status_valid(int status)144 int http_status_valid(int status)
145 {
146 	if (status == 200)
147 		return 0;
148 
149 	if (status == 401 || status == 403)
150 		return RC_DDNS_RSP_AUTH_FAIL;
151 
152 	if (status >= 500 && status < 600)
153 		return RC_DDNS_RSP_RETRY_LATER;
154 
155 	return RC_DDNS_RSP_NOTOK;
156 }
157 
http_set_port(http_t * client,int port)158 int http_set_port(http_t *client, int port)
159 {
160 	ASSERT(client);
161 	return tcp_set_port(&client->tcp, port);
162 }
163 
http_get_port(http_t * client,int * port)164 int http_get_port(http_t *client, int *port)
165 {
166 	ASSERT(client);
167 	return tcp_get_port(&client->tcp, port);
168 }
169 
170 
http_set_remote_name(http_t * client,const char * name)171 int http_set_remote_name(http_t *client, const char *name)
172 {
173 	ASSERT(client);
174 	return tcp_set_remote_name(&client->tcp, name);
175 }
176 
http_get_remote_name(http_t * client,const char ** name)177 int http_get_remote_name(http_t *client, const char **name)
178 {
179 	ASSERT(client);
180 	return tcp_get_remote_name(&client->tcp, name);
181 }
182 
http_set_remote_timeout(http_t * client,int timeout)183 int http_set_remote_timeout(http_t *client, int timeout)
184 {
185 	ASSERT(client);
186 	return tcp_set_remote_timeout(&client->tcp, timeout);
187 }
188 
http_get_remote_timeout(http_t * client,int * timeout)189 int http_get_remote_timeout(http_t *client, int *timeout)
190 {
191 	ASSERT(client);
192 	return tcp_get_remote_timeout(&client->tcp, timeout);
193 }
194 
195 /**
196  * Local Variables:
197  *  indent-tabs-mode: t
198  *  c-file-style: "linux"
199  * End:
200  */
201