Permalink
Browse files

Peter Sylvester brought code that now allows a callback to modified t…

…he URL

even when the multi interface is used, and then libcurl will simulate a
"follow location" to that new URL. Test 509 was added to test this feature.
  • Loading branch information...
bagder committed Jan 12, 2004
1 parent 5173bab commit 3a61c98b6537b69db9b225caa30ec52fc7101aa6
Showing with 623 additions and 177 deletions.
  1. +4 −0 CHANGES
  2. +169 −149 lib/multi.c
  3. +1 −1 tests/data/Makefile.am
  4. +51 −0 tests/data/test509
  5. +5 −1 tests/libtest/Makefile.am
  6. +260 −0 tests/libtest/lib509.c
  7. +133 −26 tests/stunnel.pem
View
@@ -7,6 +7,10 @@
Changelog
Daniel (12 January 2004)
+- Peter Sylvester brought code that now allows a callback to modified the URL
+ even when the multi interface is used, and then libcurl will simulate a
+ "follow location" to that new URL. Test 509 was added to test this feature.
+
- Extended the time we retry servers in the test script, and I also made it
retry the https and ftps servers before they are considered bad. I believe
the previous approach could turn problematic on really slow hosts.
View
@@ -320,45 +320,62 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
easy=multi->easy.next;
while(easy) {
-
#ifdef CURLDEBUG
fprintf(stderr, "HANDLE %p: State: %x\n",
(char *)easy, easy->state);
#endif
+ do {
+ if (CURLM_STATE_WAITCONNECT <= easy->state &&
+ easy->state <= CURLM_STATE_DO &&
+ easy->easy_handle->change.url_changed) {
+ char *gotourl;
+ Curl_posttransfer(easy->easy_handle);
- switch(easy->state) {
- case CURLM_STATE_INIT:
- /* init this transfer. */
- easy->result=Curl_pretransfer(easy->easy_handle);
-
- if(CURLE_OK == easy->result) {
- /* after init, go CONNECT */
- easy->state = CURLM_STATE_CONNECT;
- result = CURLM_CALL_MULTI_PERFORM;
-
- easy->easy_handle->state.used_interface = Curl_if_multi;
+ gotourl = strdup(easy->easy_handle->change.url);
+ easy->easy_handle->change.url_changed = FALSE;
+ easy->result = Curl_follow(easy->easy_handle, gotourl);
+ if(CURLE_OK == easy->result)
+ easy->state = CURLM_STATE_CONNECT;
+ else
+ free(gotourl);
}
- break;
+
+ easy->easy_handle->change.url_changed = FALSE;
- case CURLM_STATE_CONNECT:
- /* Connect. We get a connection identifier filled in. */
- Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE);
- easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn, &async);
+ switch(easy->state) {
+ case CURLM_STATE_INIT:
+ /* init this transfer. */
+ easy->result=Curl_pretransfer(easy->easy_handle);
- if(CURLE_OK == easy->result) {
- if(async)
- /* We're now waiting for an asynchronous name lookup */
- easy->state = CURLM_STATE_WAITRESOLVE;
- else {
- /* after the connect has been sent off, go WAITCONNECT */
- easy->state = CURLM_STATE_WAITCONNECT;
- result = CURLM_CALL_MULTI_PERFORM;
+ if(CURLE_OK == easy->result) {
+ /* after init, go CONNECT */
+ easy->state = CURLM_STATE_CONNECT;
+ result = CURLM_CALL_MULTI_PERFORM;
+
+ easy->easy_handle->state.used_interface = Curl_if_multi;
}
- }
- break;
+ break;
- case CURLM_STATE_WAITRESOLVE:
- /* awaiting an asynch name resolve to complete */
+ case CURLM_STATE_CONNECT:
+ /* Connect. We get a connection identifier filled in. */
+ Curl_pgrsTime(easy->easy_handle, TIMER_STARTSINGLE);
+ easy->result = Curl_connect(easy->easy_handle, &easy->easy_conn,
+ &async);
+
+ if(CURLE_OK == easy->result) {
+ if(async)
+ /* We're now waiting for an asynchronous name lookup */
+ easy->state = CURLM_STATE_WAITRESOLVE;
+ else {
+ /* after the connect has been sent off, go WAITCONNECT */
+ easy->state = CURLM_STATE_WAITCONNECT;
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ }
+ break;
+
+ case CURLM_STATE_WAITRESOLVE:
+ /* awaiting an asynch name resolve to complete */
{
struct Curl_dns_entry *dns;
@@ -387,146 +404,149 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
}
break;
- case CURLM_STATE_WAITCONNECT:
- /* awaiting a completion of an asynch connect */
- easy->result = Curl_is_connected(easy->easy_conn,
- easy->easy_conn->sock[FIRSTSOCKET],
- &connected);
- if(connected)
- easy->result = Curl_protocol_connect(easy->easy_conn, NULL);
-
- if(CURLE_OK != easy->result) {
- /* failure detected */
- Curl_disconnect(easy->easy_conn); /* close the connection */
- easy->easy_conn = NULL; /* no more connection */
- break;
- }
+ case CURLM_STATE_WAITCONNECT:
+ /* awaiting a completion of an asynch connect */
+ easy->result = Curl_is_connected(easy->easy_conn,
+ easy->easy_conn->sock[FIRSTSOCKET],
+ &connected);
+ if(connected)
+ easy->result = Curl_protocol_connect(easy->easy_conn, NULL);
- if(connected) {
- /* after the connect has completed, go DO */
- easy->state = CURLM_STATE_DO;
- result = CURLM_CALL_MULTI_PERFORM;
- }
- break;
+ if(CURLE_OK != easy->result) {
+ /* failure detected */
+ Curl_disconnect(easy->easy_conn); /* close the connection */
+ easy->easy_conn = NULL; /* no more connection */
+ break;
+ }
- case CURLM_STATE_DO:
- /* Do the fetch or put request */
- easy->result = Curl_do(&easy->easy_conn);
- if(CURLE_OK == easy->result) {
-
- /* after do, go PERFORM... or DO_MORE */
- if(easy->easy_conn->bits.do_more) {
- /* we're supposed to do more, but we need to sit down, relax
- and wait a little while first */
- easy->state = CURLM_STATE_DO_MORE;
- result = CURLM_OK;
+ if(connected) {
+ /* after the connect has completed, go DO */
+ easy->state = CURLM_STATE_DO;
+ result = CURLM_CALL_MULTI_PERFORM;
}
- else {
- /* we're done with the DO, now PERFORM */
- easy->result = Curl_readwrite_init(easy->easy_conn);
- if(CURLE_OK == easy->result) {
- easy->state = CURLM_STATE_PERFORM;
- result = CURLM_CALL_MULTI_PERFORM;
+ break;
+
+ case CURLM_STATE_DO:
+ /* Do the fetch or put request */
+ easy->result = Curl_do(&easy->easy_conn);
+ if(CURLE_OK == easy->result) {
+
+ /* after do, go PERFORM... or DO_MORE */
+ if(easy->easy_conn->bits.do_more) {
+ /* we're supposed to do more, but we need to sit down, relax
+ and wait a little while first */
+ easy->state = CURLM_STATE_DO_MORE;
+ result = CURLM_OK;
+ }
+ else {
+ /* we're done with the DO, now PERFORM */
+ easy->result = Curl_readwrite_init(easy->easy_conn);
+ if(CURLE_OK == easy->result) {
+ easy->state = CURLM_STATE_PERFORM;
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
}
}
- }
- break;
+ break;
- case CURLM_STATE_DO_MORE:
- /*
- * First, check if we really are ready to do more.
- */
- easy->result = Curl_is_connected(easy->easy_conn,
- easy->easy_conn->sock[SECONDARYSOCKET],
- &connected);
- if(connected) {
+ case CURLM_STATE_DO_MORE:
/*
- * When we are connected, DO MORE and then go PERFORM
+ * First, check if we really are ready to do more.
*/
- easy->result = Curl_do_more(easy->easy_conn);
-
- if(CURLE_OK == easy->result)
- easy->result = Curl_readwrite_init(easy->easy_conn);
+ easy->result =
+ Curl_is_connected(easy->easy_conn,
+ easy->easy_conn->sock[SECONDARYSOCKET],
+ &connected);
+ if(connected) {
+ /*
+ * When we are connected, DO MORE and then go PERFORM
+ */
+ easy->result = Curl_do_more(easy->easy_conn);
+
+ if(CURLE_OK == easy->result)
+ easy->result = Curl_readwrite_init(easy->easy_conn);
- if(CURLE_OK == easy->result) {
- easy->state = CURLM_STATE_PERFORM;
- result = CURLM_CALL_MULTI_PERFORM;
+ if(CURLE_OK == easy->result) {
+ easy->state = CURLM_STATE_PERFORM;
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
}
- }
- break;
+ break;
- case CURLM_STATE_PERFORM:
- /* read/write data if it is ready to do so */
- easy->result = Curl_readwrite(easy->easy_conn, &done);
-
- if(easy->result) {
- /* The transfer phase returned error, we mark the connection to get
- * closed to prevent being re-used. This is becasue we can't
- * possibly know if the connection is in a good shape or not now. */
- easy->easy_conn->bits.close = TRUE;
-
- if(-1 !=easy->easy_conn->sock[SECONDARYSOCKET]) {
- /* if we failed anywhere, we must clean up the secondary socket if
- it was used */
- sclose(easy->easy_conn->sock[SECONDARYSOCKET]);
- easy->easy_conn->sock[SECONDARYSOCKET]=-1;
+ case CURLM_STATE_PERFORM:
+ /* read/write data if it is ready to do so */
+ easy->result = Curl_readwrite(easy->easy_conn, &done);
+
+ if(easy->result) {
+ /* The transfer phase returned error, we mark the connection to get
+ * closed to prevent being re-used. This is becasue we can't
+ * possibly know if the connection is in a good shape or not now. */
+ easy->easy_conn->bits.close = TRUE;
+
+ if(-1 !=easy->easy_conn->sock[SECONDARYSOCKET]) {
+ /* if we failed anywhere, we must clean up the secondary socket if
+ it was used */
+ sclose(easy->easy_conn->sock[SECONDARYSOCKET]);
+ easy->easy_conn->sock[SECONDARYSOCKET]=-1;
+ }
+ Curl_posttransfer(easy->easy_handle);
+ Curl_done(easy->easy_conn);
}
- Curl_posttransfer(easy->easy_handle);
- Curl_done(easy->easy_conn);
- }
- /* after the transfer is done, go DONE */
- else if(TRUE == done) {
-
- /* call this even if the readwrite function returned error */
- Curl_posttransfer(easy->easy_handle);
-
- /* When we follow redirects, must to go back to the CONNECT state */
- if(easy->easy_conn->newurl) {
- char *newurl = easy->easy_conn->newurl;
- easy->easy_conn->newurl = NULL;
- easy->result = Curl_follow(easy->easy_handle, newurl);
- if(CURLE_OK == easy->result) {
- easy->state = CURLM_STATE_CONNECT;
- result = CURLM_CALL_MULTI_PERFORM;
+ /* after the transfer is done, go DONE */
+ else if(TRUE == done) {
+
+ /* call this even if the readwrite function returned error */
+ Curl_posttransfer(easy->easy_handle);
+
+ /* When we follow redirects, must to go back to the CONNECT state */
+ if(easy->easy_conn->newurl) {
+ char *newurl = easy->easy_conn->newurl;
+ easy->easy_conn->newurl = NULL;
+ easy->result = Curl_follow(easy->easy_handle, newurl);
+ if(CURLE_OK == easy->result) {
+ easy->state = CURLM_STATE_CONNECT;
+ result = CURLM_CALL_MULTI_PERFORM;
+ }
+ }
+ else {
+ easy->state = CURLM_STATE_DONE;
+ result = CURLM_CALL_MULTI_PERFORM;
}
}
- else {
- easy->state = CURLM_STATE_DONE;
- result = CURLM_CALL_MULTI_PERFORM;
- }
- }
- break;
- case CURLM_STATE_DONE:
- /* post-transfer command */
- easy->result = Curl_done(easy->easy_conn);
+ break;
+ case CURLM_STATE_DONE:
+ /* post-transfer command */
+ easy->result = Curl_done(easy->easy_conn);
- /* after we have DONE what we're supposed to do, go COMPLETED, and
- it doesn't matter what the Curl_done() returned! */
- easy->state = CURLM_STATE_COMPLETED;
- break;
+ /* after we have DONE what we're supposed to do, go COMPLETED, and
+ it doesn't matter what the Curl_done() returned! */
+ easy->state = CURLM_STATE_COMPLETED;
+ break;
- case CURLM_STATE_COMPLETED:
- /* this is a completed transfer, it is likely to still be connected */
+ case CURLM_STATE_COMPLETED:
+ /* this is a completed transfer, it is likely to still be connected */
- /* This node should be delinked from the list now and we should post
- an information message that we are complete. */
- break;
- default:
- return CURLM_INTERNAL_ERROR;
- }
+ /* This node should be delinked from the list now and we should post
+ an information message that we are complete. */
+ break;
+ default:
+ return CURLM_INTERNAL_ERROR;
+ }
- if(CURLM_STATE_COMPLETED != easy->state) {
- if(CURLE_OK != easy->result) {
- /*
- * If an error was returned, and we aren't in completed state now,
- * then we go to completed and consider this transfer aborted. */
- easy->state = CURLM_STATE_COMPLETED;
+ if(CURLM_STATE_COMPLETED != easy->state) {
+ if(CURLE_OK != easy->result) {
+ /*
+ * If an error was returned, and we aren't in completed state now,
+ * then we go to completed and consider this transfer aborted. */
+ easy->state = CURLM_STATE_COMPLETED;
+ }
+ else
+ /* this one still lives! */
+ (*running_handles)++;
}
- else
- /* this one still lives! */
- (*running_handles)++;
- }
+
+ } while (easy->easy_handle->change.url_changed);
if ((CURLM_STATE_COMPLETED == easy->state) && !easy->msg) {
/* clear out the usage of the shared DNS cache */
View
@@ -24,4 +24,4 @@ test62 test63 test64 test65 test66 test144 test145 test67 test68 test41 \
test40 test42 test69 test70 test71 test72 test73 test146 test505 \
test74 test75 test76 test77 test78 test147 test148 test506 test79 test80 \
test81 test82 test83 test84 test85 test86 test87 test507 test149 test88 \
-test89 test90 test508 test91 test92 test203 test93 test94 test95
+test89 test90 test508 test91 test92 test203 test93 test94 test95 test509
Oops, something went wrong.

0 comments on commit 3a61c98

Please sign in to comment.