Subversion Repositories Kolibri OS

Rev

Rev 3584 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3584 Rev 3616
Line 61... Line 61...
61
 
61
 
62
/* uncomment this to use scheduler based calling
62
/* uncomment this to use scheduler based calling
63
#define FETCHER_CURLL_SCHEDULED 1
63
#define FETCHER_CURLL_SCHEDULED 1
Line 64... Line -...
64
*/
-
 
65
 
-
 
66
typedef int X509_STORE_CTX;
-
 
67
typedef int X509;
-
 
68
#define CURL_ERROR_SIZE 0
-
 
69
typedef int CURLcode;
-
 
70
typedef int curl_infotype;
-
 
71
/** SSL certificate info */
-
 
72
struct cert_info {
-
 
73
	X509 *cert;		/**< Pointer to certificate */
-
 
Line 74... Line -...
74
	long err;		/**< OpenSSL error code */
-
 
75
};
64
*/
76
 
65
 
-
 
66
 
77
/** Information for a single fetch. */
67
struct fetch_curl_context {
-
 
68
	struct fetch_curl_context *r_next, *r_prev;
78
struct curl_fetch_info {
69
 
79
	struct fetch *fetch_handle; /**< The fetch handle we're parented by. */
-
 
80
	CURL * curl_handle;	/**< cURL handle if being fetched, or 0. */
70
	struct fetch *fetchh; /**< Handle for this fetch */
81
	bool had_headers;	/**< Headers have been processed. */
-
 
82
	bool abort;		/**< Abort requested. */
-
 
83
	bool stopped;		/**< Download stopped on purpose. */
-
 
84
	bool only_2xx;		/**< Only HTTP 2xx responses acceptable. */
-
 
85
	bool downgrade_tls;	/**< Downgrade to TLS <= 1.0 */
-
 
86
	nsurl *url;		/**< URL of this fetch. */
-
 
87
	lwc_string *host;	/**< The hostname of this fetch. */
-
 
88
	struct curl_slist *headers;	/**< List of request headers. */
-
 
89
	char *location;		/**< Response Location header, or 0. */
-
 
90
	unsigned long content_length;	/**< Response Content-Length, or 0. */
-
 
91
	char *cookie_string;	/**< Cookie string for this fetch */
-
 
92
	char *realm;		/**< HTTP Auth Realm */
-
 
93
	char *post_urlenc;	/**< Url encoded POST string, or 0. */
-
 
94
	long http_code; /**< HTTP result code from cURL. */
-
 
95
	struct curl_httppost *post_multipart;	/**< Multipart post data, or 0. */
-
 
96
#define MAX_CERTS 10
-
 
Line 97... Line -...
97
	struct cert_info cert_data[MAX_CERTS];	/**< HTTPS certificate data */
-
 
98
	unsigned int last_progress_update;	/**< Time of last progress update */
71
 
99
};
72
	bool aborted; /**< Flag indicating fetch has been aborted */
Line 100... Line 73...
100
 
73
	bool locked; /**< Flag indicating entry is already entered */
101
struct cache_handle {
-
 
102
	CURL *handle; /**< The cached cURL handle */
74
 
Line 103... Line -...
103
	lwc_string *host;   /**< The host for which this handle is cached */
-
 
104
 
-
 
105
	struct cache_handle *r_prev; /**< Previous cached handle in ring. */
-
 
106
	struct cache_handle *r_next; /**< Next cached handle in ring. */
-
 
107
};
75
	nsurl *url; /**< The full url the fetch refers to */
108
 
-
 
109
CURLM *fetch_curl_multi;		/**< Global cURL multi handle. */
76
	char *path; /**< The actual path to be used with open() */
110
/** Curl handle with default options set; not used for transfers. */
-
 
111
static CURL *fetch_blank_curl;
-
 
112
static struct cache_handle *curl_handle_ring = 0; /**< Ring of cached handles */
77
 
113
static int curl_fetchers_registered = 0;
78
	time_t file_etag; /**< Request etag for file (previous st.m_time) */
114
static bool curl_with_openssl;
79
};
115
 
80
 
116
static char fetch_error_buffer[CURL_ERROR_SIZE]; /**< Error buffer for cURL. */
81
static struct fetch_curl_context *ring = NULL;
117
static char fetch_proxy_userpwd[100];	/**< Proxy authentication details. */
82
 
118
 
83
 
119
static bool fetch_curl_initialise(lwc_string *scheme);
84
static bool fetch_curl_initialise(lwc_string *scheme); //here
120
static void fetch_curl_finalise(lwc_string *scheme);
85
static void fetch_curl_finalise(lwc_string *scheme); //here
121
static bool fetch_curl_can_fetch(const nsurl *url);
-
 
122
static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
-
 
123
		 bool only_2xx, bool downgrade_tls, const char *post_urlenc,
-
 
124
		 const struct fetch_multipart_data *post_multipart,
-
 
125
		 const char **headers);
-
 
126
static bool fetch_curl_start(void *vfetch);
-
 
127
static bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch,
-
 
-
 
86
static bool fetch_curl_can_fetch(const nsurl *url); //here
128
		CURL *handle);
87
static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
129
static CURL *fetch_curl_get_handle(lwc_string *host);
-
 
130
static void fetch_curl_cache_handle(CURL *handle, lwc_string *host);
88
		 bool only_2xx, bool downgrade_tls, const char *post_urlenc,
131
static CURLcode fetch_curl_set_options(struct curl_fetch_info *f);
89
		 const struct fetch_multipart_data *post_multipart,
132
static CURLcode fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx,
-
 
133
				     void *p);
-
 
134
static void fetch_curl_abort(void *vf);
-
 
135
static void fetch_curl_stop(struct curl_fetch_info *f);
-
 
136
static void fetch_curl_free(void *f);
-
 
137
static void fetch_curl_poll(lwc_string *scheme_ignored);
-
 
138
static void fetch_curl_done(CURL *curl_handle, CURLcode result);
-
 
139
static int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
-
 
140
		double ultotal, double ulnow);
-
 
141
static int fetch_curl_ignore_debug(CURL *handle,
-
 
142
				   curl_infotype type,
-
 
143
				   char *data,
-
 
144
				   size_t size,
-
 
145
				   void *userptr);
-
 
146
static size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
-
 
147
			      void *_f);
-
 
148
static size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
-
 
149
				void *_f);
-
 
150
static bool fetch_curl_process_headers(struct curl_fetch_info *f);
-
 
Line 151... Line 90...
151
static struct curl_httppost *fetch_curl_post_convert(
90
		 const char **headers); //here
152
		const struct fetch_multipart_data *control);
91
static bool fetch_curl_start(void *vfetch); //here 
153
static int fetch_curl_verify_callback(int preverify_ok,
92
 
Line 171... Line 110...
171
LOG(("curl register\n"));
110
LOG(("curl register\n"));
Line 172... Line 111...
172
 
111
 
Line 173... Line 112...
173
lwc_intern_string("http", SLEN("http"), &scheme);
112
lwc_intern_string("http", SLEN("http"), &scheme);
174
 
113
 
175
	if (!fetch_add_fetcher(scheme,
114
	if (!fetch_add_fetcher(scheme,
176
				fetch_curl_initialise,
115
				fetch_curl_initialise, //here
177
				fetch_curl_can_fetch,
116
				fetch_curl_can_fetch, //here
178
				fetch_curl_setup,
117
				fetch_curl_setup,
179
				fetch_curl_start,
118
				fetch_curl_start,
180
				fetch_curl_abort,
119
				fetch_curl_abort, //here
181
				fetch_curl_free,
120
				fetch_curl_free, //here
182
#ifdef FETCHER_CURLL_SCHEDULED
121
#ifdef FETCHER_CURLL_SCHEDULED
183
				       NULL,
122
				       NULL,
184
#else
123
#else
185
				fetch_curl_poll,
124
				fetch_curl_poll, //here
186
#endif
125
#endif
187
				fetch_curl_finalise)) {
126
				fetch_curl_finalise)) {  //here
Line 188... Line 127...
188
			LOG(("Unable to register cURL fetcher for HTTP"));
127
			LOG(("Unable to register cURL fetcher for HTTP"));
Line 229... Line 168...
229
void fetch_curl_finalise(lwc_string *scheme)
168
void fetch_curl_finalise(lwc_string *scheme)
230
{
169
{
231
LOG(("curl finali\n"));
170
LOG(("curl finali\n"));
232
}
171
}
Line 233... Line 172...
233
 
172
 
234
bool fetch_curl_can_fetch(const nsurl *url)
173
static bool fetch_curl_can_fetch(const nsurl *url)
235
{
174
{
236
	LOG(("curl can fetch\n"));
175
	LOG(("curl can fetch\n"));
237
	return false;
176
	return true; //let's lie a bit
Line 238... Line 177...
238
}
177
}
239
 
178
 
240
/**
179
/**
Line 257... Line 196...
257
 *
196
 *
258
 * Some private data can be passed as the last parameter to fetch_start, and
197
 * Some private data can be passed as the last parameter to fetch_start, and
259
 * callbacks will contain this.
198
 * callbacks will contain this.
260
 */
199
 */
Line 261... Line 200...
261
 
200
 
-
 
201
void * fetch_curl_setup (struct fetch *fetchh,
-
 
202
		 nsurl *url,
-
 
203
		 bool only_2xx,
262
void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
204
		 bool downgrade_tls,
263
		 bool only_2xx, bool downgrade_tls, const char *post_urlenc,
205
		 const char *post_urlenc,
264
		 const struct fetch_multipart_data *post_multipart,
206
		 const struct fetch_multipart_data *post_multipart,
265
		 const char **headers)
207
		 const char **headers)
-
 
208
{
266
{
209
 
Line -... Line 210...
-
 
210
	LOG(("curl setup\n"));
267
LOG(("curl setup\n"));
211
	
268
 
-
 
Line -... Line 212...
-
 
212
	struct fetch_curl_context *ctx;
-
 
213
	int i;
-
 
214
 
Line 269... Line -...
269
return;
-
 
270
}
215
	ctx = calloc(1, sizeof(*ctx));
271
 
-
 
272
 
216
	if (ctx == NULL)
273
/**
-
 
274
 * Dispatch a single job
217
		return NULL;
275
 */
218
 
276
bool fetch_curl_start(void *vfetch)
219
	ctx->path = url_to_path(nsurl_access(url));
Line -... Line 220...
-
 
220
	if (ctx->path == NULL) {
Line 277... Line -...
277
{
-
 
278
LOG(("curl start\n"));
-
 
279
	return 0;
-
 
280
}
-
 
281
 
-
 
282
 
-
 
283
/**
-
 
284
 * Initiate a fetch from the queue.
-
 
285
 *
-
 
286
 * Called with a fetch structure and a CURL handle to be used to fetch the
-
 
287
 * content.
-
 
288
 *
-
 
289
 * This will return whether or not the fetch was successfully initiated.
-
 
290
 */
-
 
Line -... Line 221...
-
 
221
		free(ctx);
Line 291... Line -...
291
 
-
 
292
bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle)
222
		return NULL;
293
{
-
 
Line 294... Line -...
294
	LOG(("curl initi fetch\n"));
-
 
295
	return 0;
-
 
296
}
-
 
297
 
223
	}
298
 
224
 
Line 299... Line 225...
299
/**
225
	ctx->url = nsurl_ref(url);
300
 * Find a CURL handle to use to dispatch a job
226
 
301
 */
227
 
302
 
-
 
303
CURL *fetch_curl_get_handle(lwc_string *host)
228
	ctx->fetchh = fetchh;
304
{
229
 
305
LOG(("curl get handle\n"));
230
	RING_INSERT(ring, ctx);
-
 
231
 
306
	return 0;
232
	return ctx;
Line 307... Line -...
307
}
-
 
308
 
-
 
309
 
-
 
Line 310... Line -...
310
/**
-
 
Line 311... Line -...
311
 * Cache a CURL handle for the provided host (if wanted)
-
 
312
 */
-
 
313
 
-
 
314
void fetch_curl_cache_handle(CURL *handle, lwc_string *host)
-
 
315
{
-
 
316
	LOG(("curl cache handle\n"));
-
 
Line 317... Line 233...
317
}
233
}
318
 
234
 
319
 
235
 
Line 320... Line -...
320
/**
-
 
321
 * Set options specific for a fetch.
236
/**
322
 */
237
 * Dispatch a single job
323
 
238
 */
Line -... Line 239...
-
 
239
bool fetch_curl_start(void *vfetch)
-
 
240
{
-
 
241
LOG(("curl start\n"));
-
 
242
	return true;
324
typedef int CURLcode;
243
}
325
 
244
 
Line 326... Line 245...
326
CURLcode
245
 
327
fetch_curl_set_options(struct curl_fetch_info *f)
246
 
328
{
247
 
Line 329... Line 248...
329
	LOG(("curl set options\n"));
248
 
330
	return -1;
249
 
-
 
250
/**
331
}
251
 * Abort a fetch.
-
 
252
 */
-
 
253
 
-
 
254
void fetch_curl_abort(void *ctx)
332
 
255
{
Line -... Line 256...
-
 
256
	struct fetch_curl_context *c = ctx;
-
 
257
 
-
 
258
	/* To avoid the poll loop having to deal with the fetch context
-
 
259
	 * disappearing from under it, we simply flag the abort here.
-
 
260
	 * The poll loop itself will perform the appropriate cleanup.
-
 
261
	 */
Line 333... Line -...
333
 
-
 
334
/**
262
	c->aborted = true;
335
 * cURL SSL setup callback
263
}
336
 */
-
 
337
 
-
 
Line 338... Line 264...
338
CURLcode
264
 
-
 
265
 
339
fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
266
/**
340
{
267
 * Free a fetch structure and associated resources.
-
 
268
 */
341
	LOG(("curlcodessl\n"));
269
 
Line -... Line 270...
-
 
270
void fetch_curl_free(void *ctx)
Line 342... Line -...
342
	
-
 
343
	return -1;
271
{
344
}
-
 
Line 345... Line -...
345
 
-
 
346
 
-
 
347
/**
272
	struct fetch_curl_context *c = ctx;
348
 * Abort a fetch.
-
 
Line -... Line 273...
-
 
273
	nsurl_unref(c->url);
-
 
274
	free(c->path);
-
 
275
	RING_REMOVE(ring, c);
-
 
276
	free(ctx);
Line 349... Line -...
349
 */
-
 
350
 
277
}
351
void fetch_curl_abort(void *vf)
278
 
352
{
-
 
353
LOG(("curl abort\n"));
-
 
Line 354... Line 279...
354
}
279
static inline bool fetch_curl_send_callback(const fetch_msg *msg,
355
 
280
		struct fetch_curl_context *ctx)
-
 
281
{
-
 
282
	ctx->locked = true;
356
 
283
	fetch_send_callback(msg, ctx->fetchh);
357
/**
284
	ctx->locked = false;
Line -... Line 285...
-
 
285
 
-
 
286
	return ctx->aborted;
Line 358... Line 287...
358
 * Clean up the provided fetch object and free it.
287
}
359
 *
288
 
360
 * Will prod the queue afterwards to allow pending requests to be initiated.
-
 
361
 */
289
static bool fetch_curl_send_header(struct fetch_curl_context *ctx,
362
 
-
 
Line 363... Line 290...
363
void fetch_curl_stop(struct curl_fetch_info *f)
290
		const char *fmt, ...)
364
{
-
 
365
	LOG(("curl stop\n"));
291
{
366
}
-
 
Line -... Line 292...
-
 
292
	fetch_msg msg;
-
 
293
	char header[64];
-
 
294
	va_list ap;
-
 
295
 
Line 367... Line 296...
367
 
296
	va_start(ap, fmt);
-
 
297
 
-
 
298
	vsnprintf(header, sizeof header, fmt, ap);
368
 
299
 
369
/**
-
 
-
 
300
	va_end(ap);
Line 370... Line 301...
370
 * Free a fetch structure and associated resources.
301
 
371
 */
302
	msg.type = FETCH_HEADER;
372
 
303
	msg.data.header_or_data.buf = (const uint8_t *) header;
373
void fetch_curl_free(void *vf)
304
	msg.data.header_or_data.len = strlen(header);
374
{
305
	fetch_curl_send_callback(&msg, ctx);
375
	LOG(("curl free\n"));
306
 
Line -... Line 307...
-
 
307
	return ctx->aborted;
Line -... Line 308...
-
 
308
}
-
 
309
 
-
 
310
static void fetch_curl_process_error(struct fetch_curl_context *ctx, int code)
-
 
311
{
376
}
312
	fetch_msg msg;
377
 
313
	char buffer[1024];
-
 
314
	const char *title;
378
 
315
	char key[8];
-
 
316
 
-
 
317
	/* content is going to return error code */
379
/**
318
	fetch_set_http_code(ctx->fetchh, code);
380
 * Do some work on current fetches.
319
 
Line 381... Line -...
381
 *
-
 
382
 * Must be called regularly to make progress on fetches.
320
	/* content type */
383
 */
-
 
384
 
-
 
385
void fetch_curl_poll(lwc_string *scheme_ignored)
321
	if (fetch_curl_send_header(ctx, "Content-Type: text/html"))
386
{
-
 
387
	LOG(("curl poll\n"));
322
		goto fetch_file_process_error_aborted;
388
}
-
 
389
 
-
 
Line 390... Line -...
390
 
-
 
391
/**
323
 
392
 * Handle a completed fetch (CURLMSG_DONE from curl_multi_info_read()).
-
 
Line -... Line 324...
-
 
324
	snprintf(key, sizeof key, "HTTP%03d", code);
393
 *
325
	title = messages_get(key);
394
 * \param  curl_handle	curl easy handle of fetch
326
 
395
 */
-
 
396
 
327
	snprintf(buffer, sizeof buffer, "%s"
397
void fetch_curl_done(CURL *curl_handle, CURLcode result)
-
 
398
{
-
 
Line 399... Line -...
399
	LOG(("curl done\n"));
-
 
400
}
-
 
401
 
-
 
402
 
-
 
403
/**
-
 
Line -... Line 328...
-
 
328
			"

%s

"
-
 
329
			"

Error %d while fetching file %s

",
404
 * Callback function for fetch progress.
330
			title, title, code, nsurl_access(ctx->url));
-
 
331
 
-
 
332
	msg.type = FETCH_DATA;
-
 
333
	msg.data.header_or_data.buf = (const uint8_t *) buffer;
405
 */
334
	msg.data.header_or_data.len = strlen(buffer);
Line 406... Line -...
406
 
-
 
407
int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
-
 
408
			double ultotal, double ulnow)
-
 
409
{
335
	if (fetch_curl_send_callback(&msg, ctx))
Line -... Line 336...
-
 
336
		goto fetch_file_process_error_aborted;
410
	LOG(("curl progress\n"));
337
 
411
	return 0;
338
	msg.type = FETCH_FINISHED;
412
}
339
	fetch_curl_send_callback(&msg, ctx);
413
 
340
 
414
 
341
fetch_file_process_error_aborted:
Line 415... Line 342...
415
 
342
	return;
416
/**
343
}
417
 * Ignore everything given to it.
344
 
418
 *
-
 
419
 * Used to ignore cURL debug.
-
 
Line -... Line 345...
-
 
345
 
Line 420... Line -...
420
 */
-
 
421
 
-
 
422
int fetch_curl_ignore_debug(CURL *handle,
-
 
423
			    curl_infotype type,
-
 
424
			    char *data,
-
 
425
			    size_t size,
-
 
426
			    void *userptr)
-
 
427
{
346
static void fetch_curl_process(struct fetch_curl_context *ctx) {
Line -... Line 347...
-
 
347
	
-
 
348
	fetch_msg msg;
-
 
349
	const char * buf = "

Hello, file fetcher!

";
-
 
350
//	fetch_curl_process_error(ctx, 501);
-
 
351
//	return;
-
 
352
 
-
 
353
/* fetch is going to be successful */
-
 
354
	fetch_set_http_code(ctx->fetchh, 200);
-
 
355
 
428
	LOG(("curl igdebug\n"));
356
	/* Any callback can result in the fetch being aborted.
-
 
357
	 * Therefore, we _must_ check for this after _every_ call to
429
	return 0;
358
	 * fetch_file_send_callback().
430
}
359
	 */
Line -... Line 360...
-
 
360
 
-
 
361
	/* content type */
-
 
362
	if (fetch_curl_send_header(ctx, "Content-Type: text/html"))
-
 
363
		goto fetch_file_process_aborted;
-
 
364
 
Line 431... Line -...
431
 
-
 
432
 
365
	
433
/**
366
	/* main data loop */
434
 * Callback function for cURL.
367
 
-
 
368
		msg.type = FETCH_DATA;
Line 435... Line 369...
435
 */
369
		msg.data.header_or_data.buf = (const uint8_t *) buf;
-
 
370
		msg.data.header_or_data.len = strlen(buf);
436
 
371
		fetch_curl_send_callback(&msg, ctx);
-
 
372
			
-
 
373
	
-
 
374
 
-
 
375
	if (ctx->aborted == false) {
Line 437... Line -...
437
size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
-
 
438
		       void *_f)
-
 
439
{
376
		msg.type = FETCH_FINISHED;
Line 440... Line -...
440
	LOG(("curl callback\n"));
-
 
441
		return 0;
-
 
442
}
-
 
443
 
-
 
Line 444... Line -...
444
 
-
 
445
/**
-
 
Line 446... Line -...
446
 * Callback function for headers.
-
 
447
 *
-
 
448
 * See RFC 2616 4.2.
-