246
321
easy=multi->easy.next;
248
switch(easy->state) {
249
case CURLM_STATE_INIT:
250
/* init this transfer. */
251
easy->result=Curl_pretransfer(easy->easy_handle);
252
if(CURLE_OK == easy->result) {
253
/* after init, go CONNECT */
254
easy->state = CURLM_STATE_CONNECT;
255
result = CURLM_CALL_MULTI_PERFORM;
258
case CURLM_STATE_CONNECT:
259
if (Curl_global_host_cache_use(easy->easy_handle)) {
260
easy->easy_handle->hostcache = Curl_global_host_cache_get();
263
if (multi->hostcache == NULL) {
264
multi->hostcache = curl_hash_alloc(7, Curl_freeaddrinfo);
267
easy->easy_handle->hostcache = multi->hostcache;
270
/* Connect. We get a connection identifier filled in. */
271
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn);
273
/* after connect, go DO */
274
if(CURLE_OK == easy->result) {
275
easy->state = CURLM_STATE_DO;
276
result = CURLM_CALL_MULTI_PERFORM;
280
/* Do the fetch or put request */
281
easy->result = Curl_do(&easy->easy_conn);
282
/* after do, go PERFORM */
283
if(CURLE_OK == easy->result) {
284
if(CURLE_OK == Curl_readwrite_init(easy->easy_conn)) {
285
easy->state = CURLM_STATE_PERFORM;
286
result = CURLM_CALL_MULTI_PERFORM;
290
case CURLM_STATE_PERFORM:
291
/* read/write data if it is ready to do so */
292
easy->result = Curl_readwrite(easy->easy_conn, &done);
293
/* hm, when we follow redirects, we may need to go back to the CONNECT
295
/* after the transfer is done, go DONE */
297
/* call this even if the readwrite function returned error */
298
easy->result = Curl_posttransfer(easy->easy_handle);
299
easy->state = CURLM_STATE_DONE;
300
result = CURLM_CALL_MULTI_PERFORM;
303
case CURLM_STATE_DONE:
304
/* post-transfer command */
305
easy->result = Curl_done(easy->easy_conn);
306
/* after we have DONE what we're supposed to do, go COMPLETED */
307
if(CURLE_OK == easy->result)
324
fprintf(stderr, "HANDLE %p: State: %x\n",
325
(char *)easy, easy->state);
328
if (CURLM_STATE_WAITCONNECT <= easy->state &&
329
easy->state <= CURLM_STATE_DO &&
330
easy->easy_handle->change.url_changed) {
332
Curl_posttransfer(easy->easy_handle);
334
easy->result = Curl_done(easy->easy_conn);
335
if(CURLE_OK == easy->result) {
336
gotourl = strdup(easy->easy_handle->change.url);
337
easy->easy_handle->change.url_changed = FALSE;
338
easy->result = Curl_follow(easy->easy_handle, gotourl);
339
if(CURLE_OK == easy->result)
340
easy->state = CURLM_STATE_CONNECT;
346
easy->easy_handle->change.url_changed = FALSE;
348
switch(easy->state) {
349
case CURLM_STATE_INIT:
350
/* init this transfer. */
351
easy->result=Curl_pretransfer(easy->easy_handle);
353
if(CURLE_OK == easy->result) {
354
/* after init, go CONNECT */
355
easy->state = CURLM_STATE_CONNECT;
356
result = CURLM_CALL_MULTI_PERFORM;
358
easy->easy_handle->state.used_interface = Curl_if_multi;
362
case CURLM_STATE_CONNECT:
363
/* Connect. We get a connection identifier filled in. */
364
Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE);
365
easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn,
368
if(CURLE_OK == easy->result) {
370
/* We're now waiting for an asynchronous name lookup */
371
easy->state = CURLM_STATE_WAITRESOLVE;
373
/* after the connect has been sent off, go WAITCONNECT */
374
easy->state = CURLM_STATE_WAITCONNECT;
375
result = CURLM_CALL_MULTI_PERFORM;
380
case CURLM_STATE_WAITRESOLVE:
381
/* awaiting an asynch name resolve to complete */
383
struct Curl_dns_entry *dns = NULL;
385
/* check if we have the name resolved by now */
386
easy->result = Curl_is_resolved(easy->easy_conn, &dns);
389
/* Perform the next step in the connection phase, and then move on
390
to the WAITCONNECT state */
391
easy->result = Curl_async_resolved(easy->easy_conn);
393
if(CURLE_OK != easy->result)
394
/* if Curl_async_resolved() returns failure, the connection struct
395
is already freed and gone */
396
easy->easy_conn = NULL; /* no more connection */
398
easy->state = CURLM_STATE_WAITCONNECT;
401
if(CURLE_OK != easy->result) {
402
/* failure detected */
403
Curl_disconnect(easy->easy_conn); /* disconnect properly */
404
easy->easy_conn = NULL; /* no more connection */
410
case CURLM_STATE_WAITCONNECT:
411
/* awaiting a completion of an asynch connect */
412
easy->result = Curl_is_connected(easy->easy_conn,
413
easy->easy_conn->sock[FIRSTSOCKET],
416
easy->result = Curl_protocol_connect(easy->easy_conn, NULL);
418
if(CURLE_OK != easy->result) {
419
/* failure detected */
420
Curl_disconnect(easy->easy_conn); /* close the connection */
421
easy->easy_conn = NULL; /* no more connection */
426
/* after the connect has completed, go DO */
427
easy->state = CURLM_STATE_DO;
428
result = CURLM_CALL_MULTI_PERFORM;
433
/* Do the fetch or put request */
434
easy->result = Curl_do(&easy->easy_conn);
435
if(CURLE_OK == easy->result) {
437
/* after do, go PERFORM... or DO_MORE */
438
if(easy->easy_conn->bits.do_more) {
439
/* we're supposed to do more, but we need to sit down, relax
440
and wait a little while first */
441
easy->state = CURLM_STATE_DO_MORE;
445
/* we're done with the DO, now PERFORM */
446
easy->result = Curl_readwrite_init(easy->easy_conn);
447
if(CURLE_OK == easy->result) {
448
easy->state = CURLM_STATE_PERFORM;
449
result = CURLM_CALL_MULTI_PERFORM;
455
case CURLM_STATE_DO_MORE:
457
* First, check if we really are ready to do more.
460
Curl_is_connected(easy->easy_conn,
461
easy->easy_conn->sock[SECONDARYSOCKET],
465
* When we are connected, DO MORE and then go PERFORM
467
easy->result = Curl_do_more(easy->easy_conn);
469
if(CURLE_OK == easy->result)
470
easy->result = Curl_readwrite_init(easy->easy_conn);
472
if(CURLE_OK == easy->result) {
473
easy->state = CURLM_STATE_PERFORM;
474
result = CURLM_CALL_MULTI_PERFORM;
479
case CURLM_STATE_PERFORM:
480
/* read/write data if it is ready to do so */
481
easy->result = Curl_readwrite(easy->easy_conn, &done);
484
/* The transfer phase returned error, we mark the connection to get
485
* closed to prevent being re-used. This is becasue we can't
486
* possibly know if the connection is in a good shape or not now. */
487
easy->easy_conn->bits.close = TRUE;
489
if(CURL_SOCKET_BAD != easy->easy_conn->sock[SECONDARYSOCKET]) {
490
/* if we failed anywhere, we must clean up the secondary socket if
492
sclose(easy->easy_conn->sock[SECONDARYSOCKET]);
493
easy->easy_conn->sock[SECONDARYSOCKET]=-1;
495
Curl_posttransfer(easy->easy_handle);
496
Curl_done(easy->easy_conn);
499
/* after the transfer is done, go DONE */
500
else if(TRUE == done) {
502
/* call this even if the readwrite function returned error */
503
Curl_posttransfer(easy->easy_handle);
505
/* When we follow redirects, must to go back to the CONNECT state */
506
if(easy->easy_conn->newurl) {
507
char *newurl = easy->easy_conn->newurl;
508
easy->easy_conn->newurl = NULL;
509
easy->result = Curl_done(easy->easy_conn);
510
if(easy->result == CURLE_OK)
511
easy->result = Curl_follow(easy->easy_handle, newurl);
512
if(CURLE_OK == easy->result) {
513
easy->state = CURLM_STATE_CONNECT;
514
result = CURLM_CALL_MULTI_PERFORM;
518
easy->state = CURLM_STATE_DONE;
519
result = CURLM_CALL_MULTI_PERFORM;
523
case CURLM_STATE_DONE:
524
/* post-transfer command */
525
easy->result = Curl_done(easy->easy_conn);
527
/* after we have DONE what we're supposed to do, go COMPLETED, and
528
it doesn't matter what the Curl_done() returned! */
308
529
easy->state = CURLM_STATE_COMPLETED;
310
case CURLM_STATE_COMPLETED:
311
/* this is a completed transfer, it is likely to still be connected */
313
/* This node should be delinked from the list now and we should post
314
an information message that we are complete. */
317
return CURLM_INTERNAL_ERROR;
320
if((CURLM_STATE_COMPLETED != easy->state) &&
321
(CURLE_OK != easy->result)) {
323
* If an error was returned, and we aren't in completed now,
324
* then we go to completed and consider this transfer aborted.
326
easy->state = CURLM_STATE_COMPLETED;
328
else if(CURLM_STATE_COMPLETED != easy->state)
329
/* this one still lives! */
330
(*running_handles)++;
532
case CURLM_STATE_COMPLETED:
533
/* this is a completed transfer, it is likely to still be connected */
535
/* This node should be delinked from the list now and we should post
536
an information message that we are complete. */
539
return CURLM_INTERNAL_ERROR;
542
if(CURLM_STATE_COMPLETED != easy->state) {
543
if(CURLE_OK != easy->result) {
545
* If an error was returned, and we aren't in completed state now,
546
* then we go to completed and consider this transfer aborted. */
547
easy->state = CURLM_STATE_COMPLETED;
550
/* this one still lives! */
551
(*running_handles)++;
554
} while (easy->easy_handle->change.url_changed);
556
if ((CURLM_STATE_COMPLETED == easy->state) && !easy->msg) {
557
/* clear out the usage of the shared DNS cache */
558
easy->easy_handle->hostcache = NULL;
560
/* now add a node to the Curl_message linked list with this info */
561
msg = (struct Curl_message *)malloc(sizeof(struct Curl_message));
564
return CURLM_OUT_OF_MEMORY;
566
msg->extmsg.msg = CURLMSG_DONE;
567
msg->extmsg.easy_handle = easy->easy_handle;
568
msg->extmsg.data.result = easy->result;
572
easy->msg_num = 1; /* there is one unread message here */
574
multi->num_msgs++; /* increase message counter */
332
577
easy = easy->next; /* operate on next handle */
337
583
CURLMcode curl_multi_cleanup(CURLM *multi_handle)
339
585
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
586
struct Curl_one_easy *easy;
587
struct Curl_one_easy *nexteasy;
340
589
if(GOOD_MULTI_HANDLE(multi)) {
341
590
multi->type = 0; /* not good anymore */
342
curl_hash_destroy(multi->hostcache);
591
Curl_hash_destroy(multi->hostcache);
343
593
/* remove all easy handles */
594
easy = multi->easy.next;
597
/* clear out the usage of the shared DNS cache */
598
easy->easy_handle->hostcache = NULL;