1 #include <libubox/ustream-ssl.h>
3 #include "uclient-utils.h"
4 #include "uclient-backend.h"
6 struct uclient_url __hidden *
7 uclient_get_url(const char *url_str, const char *auth_str)
9 static const struct uclient_backend *backends[] = {
10 &uclient_backend_http,
13 const struct uclient_backend *backend;
14 const char * const *prefix = NULL;
15 struct uclient_url *url;
17 char *host_buf, *uri_buf, *auth_buf, *next;
20 for (i = 0; i < ARRAY_SIZE(backends); i++) {
23 for (prefix = backends[i]->prefix; *prefix; prefix++) {
24 prefix_len = strlen(*prefix);
26 if (!strncmp(url_str, *prefix, prefix_len))
33 url_str += prefix_len;
34 backend = backends[i];
41 next = strchr(url_str, '/');
44 host_len = next - url_str;
47 host_len = strlen(url_str);
50 url = calloc_a(sizeof(*url),
51 &host_buf, host_len + 1,
52 &uri_buf, strlen(location) + 1,
53 &auth_buf, auth_str ? strlen(auth_str) + 1 : 0);
55 url->backend = backend;
56 url->location = strcpy(uri_buf, location);
57 url->prefix = prefix - backend->prefix;
59 url->host = strncpy(host_buf, url_str, host_len);
61 next = strchr(host_buf, '@');
66 if (uclient_urldecode(host_buf, host_buf, false) < 0)
72 if (!url->auth && auth_str)
73 url->auth = strcpy(auth_buf, auth_str);
75 /* Literal IPv6 address */
76 if (*url->host == '[') {
78 next = strrchr(url->host, ']');
86 next = strrchr(url->host, ':');
98 struct uclient *uclient_new(const char *url_str, const struct uclient_cb *cb)
101 struct uclient_url *url;
103 url = uclient_get_url(url_str, NULL);
107 cl = url->backend->alloc();
111 cl->backend = url->backend;
118 int uclient_connect_url(struct uclient *cl, const char *url_str)
120 struct uclient_url *url = cl->url;
121 const struct uclient_backend *backend = cl->backend;
124 url = uclient_get_url(url_str, NULL);
128 if (url->backend != cl->backend)
134 if (backend->update_url)
135 backend->update_url(cl);
138 return backend->connect(cl);
141 void uclient_free(struct uclient *cl)
143 struct uclient_url *url = cl->url;
145 if (cl->backend->free)
146 cl->backend->free(cl);
153 int uclient_write(struct uclient *cl, char *buf, int len)
155 if (!cl->backend->write)
158 return cl->backend->write(cl, buf, len);
161 int uclient_request(struct uclient *cl)
163 if (!cl->backend->request)
166 return cl->backend->request(cl);
169 int uclient_read(struct uclient *cl, char *buf, int len)
171 if (!cl->backend->read)
174 return cl->backend->read(cl, buf, len);
177 static void __uclient_backend_change_state(struct uloop_timeout *timeout)
179 struct uclient *cl = container_of(timeout, struct uclient, timeout);
181 if (cl->error_code && cl->cb->error)
182 cl->cb->error(cl, cl->error_code);
183 else if (cl->eof && cl->cb->data_eof)
184 cl->cb->data_eof(cl);
187 static void uclient_backend_change_state(struct uclient *cl)
189 cl->timeout.cb = __uclient_backend_change_state;
190 uloop_timeout_set(&cl->timeout, 1);
193 void __hidden uclient_backend_set_error(struct uclient *cl, int code)
198 cl->error_code = code;
199 uclient_backend_change_state(cl);
202 void __hidden uclient_backend_set_eof(struct uclient *cl)
204 if (cl->eof || cl->error_code)
208 uclient_backend_change_state(cl);
211 void __hidden uclient_backend_reset_state(struct uclient *cl)
215 uloop_timeout_cancel(&cl->timeout);