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
);
58 url
->host
= strncpy(host_buf
, url_str
, host_len
);
60 next
= strchr(host_buf
, '@');
65 if (uclient_urldecode(host_buf
, host_buf
, false) < 0)
71 if (!url
->auth
&& auth_str
)
72 url
->auth
= strcpy(auth_buf
, auth_str
);
74 /* Literal IPv6 address */
75 if (*url
->host
== '[') {
77 next
= strrchr(url
->host
, ']');
85 next
= strrchr(url
->host
, ':');
97 struct uclient
*uclient_new(const char *url_str
, const struct uclient_cb
*cb
)
100 struct uclient_url
*url
;
102 url
= uclient_get_url(url_str
, NULL
);
106 cl
= url
->backend
->alloc();
110 cl
->backend
= url
->backend
;
117 int uclient_connect_url(struct uclient
*cl
, const char *url_str
)
119 struct uclient_url
*url
= cl
->url
;
120 const struct uclient_backend
*backend
= cl
->backend
;
123 url
= uclient_get_url(url_str
, NULL
);
127 if (url
->backend
!= cl
->backend
)
133 if (backend
->update_url
)
134 backend
->update_url(cl
);
137 return backend
->connect(cl
);
140 void uclient_free(struct uclient
*cl
)
142 struct uclient_url
*url
= cl
->url
;
144 if (cl
->backend
->free
)
145 cl
->backend
->free(cl
);
152 int uclient_write(struct uclient
*cl
, char *buf
, int len
)
154 if (!cl
->backend
->write
)
157 return cl
->backend
->write(cl
, buf
, len
);
160 int uclient_request(struct uclient
*cl
)
162 if (!cl
->backend
->request
)
165 return cl
->backend
->request(cl
);
168 int uclient_read(struct uclient
*cl
, char *buf
, int len
)
170 if (!cl
->backend
->read
)
173 return cl
->backend
->read(cl
, buf
, len
);
176 static void __uclient_backend_change_state(struct uloop_timeout
*timeout
)
178 struct uclient
*cl
= container_of(timeout
, struct uclient
, timeout
);
180 if (cl
->error
&& cl
->cb
->error
)
182 else if (cl
->eof
&& cl
->cb
->data_eof
)
183 cl
->cb
->data_eof(cl
);
186 static void uclient_backend_change_state(struct uclient
*cl
)
188 cl
->timeout
.cb
= __uclient_backend_change_state
;
189 uloop_timeout_set(&cl
->timeout
, 1);
192 void __hidden
uclient_backend_set_error(struct uclient
*cl
)
198 uclient_backend_change_state(cl
);
201 void __hidden
uclient_backend_set_eof(struct uclient
*cl
)
203 if (cl
->eof
|| cl
->error
)
207 uclient_backend_change_state(cl
);
210 void __hidden
uclient_backend_reset_state(struct uclient
*cl
)
214 uloop_timeout_cancel(&cl
->timeout
);