1 #include <libubox/ustream-ssl.h>
3 #include "uclient-utils.h"
4 #include "uclient-backend.h"
6 static struct uclient_url
*uclient_get_url(const char *url_str
)
8 static const struct uclient_backend
*backends
[] = {
12 const struct uclient_backend
*backend
;
13 const char * const *prefix
= NULL
;
14 struct uclient_url
*url
;
18 for (i
= 0; i
< ARRAY_SIZE(backends
); i
++) {
21 for (prefix
= backends
[i
]->prefix
; *prefix
; prefix
++) {
22 prefix_len
= strlen(*prefix
);
24 if (!strncmp(url_str
, *prefix
, prefix_len
))
31 url_str
+= prefix_len
;
32 backend
= backends
[i
];
39 url
= calloc_a(sizeof(*url
), &url_buf
, strlen(url_str
) + 1);
40 url
->backend
= backend
;
41 strcpy(url_buf
, url_str
);
43 next
= strchr(url_buf
, '/');
46 url
->location
= next
+ 1;
52 next
= strchr(url_buf
, '@');
57 if (uclient_urldecode(url_buf
, url_buf
, false) < 0)
63 /* Literal IPv6 address */
64 if (*url
->host
== '[') {
66 next
= strrchr(url
->host
, ']');
74 next
= strrchr(url
->host
, ':');
86 struct uclient
*uclient_new(const char *url_str
, const struct uclient_cb
*cb
)
89 struct uclient_url
*url
;
91 url
= uclient_get_url(url_str
);
95 cl
= url
->backend
->alloc();
99 cl
->backend
= url
->backend
;
106 int uclient_connect_url(struct uclient
*cl
, const char *url_str
)
108 struct uclient_url
*url
= cl
->url
;
109 const struct uclient_backend
*backend
= cl
->backend
;
112 url
= uclient_get_url(url_str
);
116 if (url
->backend
!= cl
->backend
)
122 if (backend
->update_url
)
123 backend
->update_url(cl
);
126 return backend
->connect(cl
);
129 void uclient_free(struct uclient
*cl
)
131 struct uclient_url
*url
= cl
->url
;
133 if (cl
->backend
->free
)
134 cl
->backend
->free(cl
);
141 int uclient_write(struct uclient
*cl
, char *buf
, int len
)
143 if (!cl
->backend
->write
)
146 return cl
->backend
->write(cl
, buf
, len
);
149 int uclient_request(struct uclient
*cl
)
151 if (!cl
->backend
->request
)
154 return cl
->backend
->request(cl
);
157 int uclient_read(struct uclient
*cl
, char *buf
, int len
)
159 if (!cl
->backend
->read
)
162 return cl
->backend
->read(cl
, buf
, len
);
165 static void __uclient_backend_change_state(struct uloop_timeout
*timeout
)
167 struct uclient
*cl
= container_of(timeout
, struct uclient
, timeout
);
169 if (cl
->error
&& cl
->cb
->error
)
171 else if (cl
->eof
&& cl
->cb
->data_eof
)
172 cl
->cb
->data_eof(cl
);
175 static void uclient_backend_change_state(struct uclient
*cl
)
177 cl
->timeout
.cb
= __uclient_backend_change_state
;
178 uloop_timeout_set(&cl
->timeout
, 1);
181 void uclient_backend_set_error(struct uclient
*cl
)
187 uclient_backend_change_state(cl
);
190 void __hidden
uclient_backend_set_eof(struct uclient
*cl
)
192 if (cl
->eof
|| cl
->error
)
196 uclient_backend_change_state(cl
);
199 void __hidden
uclient_backend_reset_state(struct uclient
*cl
)
203 uloop_timeout_cancel(&cl
->timeout
);