00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025
00026
00027
00028
00029 #ifdef CURLX_NO_MEMORY_CALLBACKS
00030 #error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined"
00031 #endif
00032
00033 #ifdef HAVE_NETINET_IN_H
00034 #include <netinet/in.h>
00035 #endif
00036 #ifdef HAVE_NETDB_H
00037 #include <netdb.h>
00038 #endif
00039 #ifdef HAVE_ARPA_INET_H
00040 #include <arpa/inet.h>
00041 #endif
00042 #ifdef HAVE_NET_IF_H
00043 #include <net/if.h>
00044 #endif
00045 #ifdef HAVE_SYS_IOCTL_H
00046 #include <sys/ioctl.h>
00047 #endif
00048
00049 #ifdef HAVE_SYS_PARAM_H
00050 #include <sys/param.h>
00051 #endif
00052
00053 #include "urldata.h"
00054 #include <curl/curl.h>
00055 #include "transfer.h"
00056 #include "vtls/vtls.h"
00057 #include "url.h"
00058 #include "getinfo.h"
00059 #include "hostip.h"
00060 #include "share.h"
00061 #include "strdup.h"
00062 #include "progress.h"
00063 #include "easyif.h"
00064 #include "select.h"
00065 #include "sendf.h"
00066 #include "connect.h"
00067 #include "slist.h"
00068 #include "amigaos.h"
00069 #include "non-ascii.h"
00070 #include "warnless.h"
00071 #include "conncache.h"
00072 #include "multiif.h"
00073 #include "sigpipe.h"
00074 #include "ssh.h"
00075
00076 #include "curl_printf.h"
00077 #include "curl_memory.h"
00078 #include "memdebug.h"
00079
00080 void Curl_version_init(void);
00081
00082
00083
00084 static void win32_cleanup(void)
00085 {
00086 #ifdef USE_WINSOCK
00087 WSACleanup();
00088 #endif
00089 #ifdef USE_WINDOWS_SSPI
00090 Curl_sspi_global_cleanup();
00091 #endif
00092 }
00093
00094
00095
00096 static CURLcode win32_init(void)
00097 {
00098 #ifdef USE_WINSOCK
00099 WORD wVersionRequested;
00100 WSADATA wsaData;
00101 int res;
00102
00103 #if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
00104 Error IPV6_requires_winsock2
00105 #endif
00106
00107 wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
00108
00109 res = WSAStartup(wVersionRequested, &wsaData);
00110
00111 if(res != 0)
00112
00113
00114 return CURLE_FAILED_INIT;
00115
00116
00117
00118
00119
00120
00121
00122 if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
00123 HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
00124
00125
00126
00127 WSACleanup();
00128 return CURLE_FAILED_INIT;
00129 }
00130
00131 #elif defined(USE_LWIPSOCK)
00132 lwip_init();
00133 #endif
00134
00135 #ifdef USE_WINDOWS_SSPI
00136 {
00137 CURLcode result = Curl_sspi_global_init();
00138 if(result)
00139 return result;
00140 }
00141 #endif
00142
00143 return CURLE_OK;
00144 }
00145
00146
00147 static unsigned int initialized;
00148 static long init_flags;
00149
00150
00151
00152
00153
00154
00155 #if defined(_WIN32_WCE)
00156 #define system_strdup _strdup
00157 #elif !defined(HAVE_STRDUP)
00158 #define system_strdup curlx_strdup
00159 #else
00160 #define system_strdup strdup
00161 #endif
00162
00163 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
00164 # pragma warning(disable:4232)
00165 #endif
00166
00167 #ifndef __SYMBIAN32__
00168
00169
00170
00171
00172 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
00173 curl_free_callback Curl_cfree = (curl_free_callback)free;
00174 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
00175 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
00176 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
00177 #if defined(WIN32) && defined(UNICODE)
00178 curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
00179 #endif
00180 #else
00181
00182
00183
00184
00185 curl_malloc_callback Curl_cmalloc;
00186 curl_free_callback Curl_cfree;
00187 curl_realloc_callback Curl_crealloc;
00188 curl_strdup_callback Curl_cstrdup;
00189 curl_calloc_callback Curl_ccalloc;
00190 #endif
00191
00192 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
00193 # pragma warning(default:4232)
00194 #endif
00195
00200 static CURLcode global_init(long flags, bool memoryfuncs)
00201 {
00202 if(initialized++)
00203 return CURLE_OK;
00204
00205 if(memoryfuncs) {
00206
00207 Curl_cmalloc = (curl_malloc_callback)malloc;
00208 Curl_cfree = (curl_free_callback)free;
00209 Curl_crealloc = (curl_realloc_callback)realloc;
00210 Curl_cstrdup = (curl_strdup_callback)system_strdup;
00211 Curl_ccalloc = (curl_calloc_callback)calloc;
00212 #if defined(WIN32) && defined(UNICODE)
00213 Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
00214 #endif
00215 }
00216
00217 if(flags & CURL_GLOBAL_SSL)
00218 if(!Curl_ssl_init()) {
00219 DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
00220 return CURLE_FAILED_INIT;
00221 }
00222
00223 if(flags & CURL_GLOBAL_WIN32)
00224 if(win32_init()) {
00225 DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
00226 return CURLE_FAILED_INIT;
00227 }
00228
00229 #ifdef __AMIGA__
00230 if(!Curl_amiga_init()) {
00231 DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
00232 return CURLE_FAILED_INIT;
00233 }
00234 #endif
00235
00236 #ifdef NETWARE
00237 if(netware_init()) {
00238 DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n"));
00239 }
00240 #endif
00241
00242 if(Curl_resolver_global_init()) {
00243 DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
00244 return CURLE_FAILED_INIT;
00245 }
00246
00247 (void)Curl_ipv6works();
00248
00249 #if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT)
00250 if(libssh2_init(0)) {
00251 DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
00252 return CURLE_FAILED_INIT;
00253 }
00254 #endif
00255
00256 if(flags & CURL_GLOBAL_ACK_EINTR)
00257 Curl_ack_eintr = 1;
00258
00259 init_flags = flags;
00260
00261 Curl_version_init();
00262
00263 return CURLE_OK;
00264 }
00265
00266
00271 CURLcode curl_global_init(long flags)
00272 {
00273 return global_init(flags, TRUE);
00274 }
00275
00276
00277
00278
00279
00280 CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
00281 curl_free_callback f, curl_realloc_callback r,
00282 curl_strdup_callback s, curl_calloc_callback c)
00283 {
00284
00285 if(!m || !f || !r || !s || !c)
00286 return CURLE_FAILED_INIT;
00287
00288 if(initialized) {
00289
00290
00291
00292 initialized++;
00293 return CURLE_OK;
00294 }
00295
00296
00297
00298 Curl_cmalloc = m;
00299 Curl_cfree = f;
00300 Curl_cstrdup = s;
00301 Curl_crealloc = r;
00302 Curl_ccalloc = c;
00303
00304
00305 return global_init(flags, FALSE);
00306 }
00307
00312 void curl_global_cleanup(void)
00313 {
00314 if(!initialized)
00315 return;
00316
00317 if(--initialized)
00318 return;
00319
00320 Curl_global_host_cache_dtor();
00321
00322 if(init_flags & CURL_GLOBAL_SSL)
00323 Curl_ssl_cleanup();
00324
00325 Curl_resolver_global_cleanup();
00326
00327 if(init_flags & CURL_GLOBAL_WIN32)
00328 win32_cleanup();
00329
00330 Curl_amiga_cleanup();
00331
00332 #if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT)
00333 (void)libssh2_exit();
00334 #endif
00335
00336 init_flags = 0;
00337 }
00338
00339
00340
00341
00342
00343 struct Curl_easy *curl_easy_init(void)
00344 {
00345 CURLcode result;
00346 struct Curl_easy *data;
00347
00348
00349 if(!initialized) {
00350 result = curl_global_init(CURL_GLOBAL_DEFAULT);
00351 if(result) {
00352
00353 DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
00354 return NULL;
00355 }
00356 }
00357
00358
00359 result = Curl_open(&data);
00360 if(result) {
00361 DEBUGF(fprintf(stderr, "Error: Curl_open failed\n"));
00362 return NULL;
00363 }
00364
00365 return data;
00366 }
00367
00368
00369
00370
00371
00372
00373 #undef curl_easy_setopt
00374 CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
00375 {
00376 va_list arg;
00377 CURLcode result;
00378
00379 if(!data)
00380 return CURLE_BAD_FUNCTION_ARGUMENT;
00381
00382 va_start(arg, tag);
00383
00384 result = Curl_setopt(data, tag, arg);
00385
00386 va_end(arg);
00387 return result;
00388 }
00389
00390 #ifdef CURLDEBUG
00391
00392 struct socketmonitor {
00393 struct socketmonitor *next;
00394 struct pollfd socket;
00395 };
00396
00397 struct events {
00398 long ms;
00399 bool msbump;
00400 int num_sockets;
00401 struct socketmonitor *list;
00402 int running_handles;
00403 };
00404
00405
00406
00407
00408
00409
00410
00411 static int events_timer(struct Curl_multi *multi,
00412 long timeout_ms,
00413 void *userp)
00414 {
00415 struct events *ev = userp;
00416 (void)multi;
00417 if(timeout_ms == -1)
00418
00419 timeout_ms = 0;
00420 else if(timeout_ms == 0)
00421
00422 timeout_ms = 1;
00423
00424 ev->ms = timeout_ms;
00425 ev->msbump = TRUE;
00426 return 0;
00427 }
00428
00429
00430
00431
00432
00433
00434 static int poll2cselect(int pollmask)
00435 {
00436 int omask=0;
00437 if(pollmask & POLLIN)
00438 omask |= CURL_CSELECT_IN;
00439 if(pollmask & POLLOUT)
00440 omask |= CURL_CSELECT_OUT;
00441 if(pollmask & POLLERR)
00442 omask |= CURL_CSELECT_ERR;
00443 return omask;
00444 }
00445
00446
00447
00448
00449
00450
00451 static short socketcb2poll(int pollmask)
00452 {
00453 short omask=0;
00454 if(pollmask & CURL_POLL_IN)
00455 omask |= POLLIN;
00456 if(pollmask & CURL_POLL_OUT)
00457 omask |= POLLOUT;
00458 return omask;
00459 }
00460
00461
00462
00463
00464
00465
00466 static int events_socket(struct Curl_easy *easy,
00467 curl_socket_t s,
00468 int what,
00469 void *userp,
00470
00471 void *socketp)
00472
00473 {
00474 struct events *ev = userp;
00475 struct socketmonitor *m;
00476 struct socketmonitor *prev=NULL;
00477
00478 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
00479 (void) easy;
00480 #endif
00481 (void)socketp;
00482
00483 m = ev->list;
00484 while(m) {
00485 if(m->socket.fd == s) {
00486
00487 if(what == CURL_POLL_REMOVE) {
00488 struct socketmonitor *nxt = m->next;
00489
00490 if(prev)
00491 prev->next = nxt;
00492 else
00493 ev->list = nxt;
00494 free(m);
00495 m = nxt;
00496 infof(easy, "socket cb: socket %d REMOVED\n", s);
00497 }
00498 else {
00499
00500
00501 m->socket.events = socketcb2poll(what);
00502 infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
00503 what&CURL_POLL_IN?"IN":"",
00504 what&CURL_POLL_OUT?"OUT":"");
00505 }
00506 break;
00507 }
00508 prev = m;
00509 m = m->next;
00510 }
00511 if(!m) {
00512 if(what == CURL_POLL_REMOVE) {
00513
00514
00515
00516
00517 }
00518 else {
00519 m = malloc(sizeof(struct socketmonitor));
00520 if(m) {
00521 m->next = ev->list;
00522 m->socket.fd = s;
00523 m->socket.events = socketcb2poll(what);
00524 m->socket.revents = 0;
00525 ev->list = m;
00526 infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
00527 what&CURL_POLL_IN?"IN":"",
00528 what&CURL_POLL_OUT?"OUT":"");
00529 }
00530 else
00531 return CURLE_OUT_OF_MEMORY;
00532 }
00533 }
00534
00535 return 0;
00536 }
00537
00538
00539
00540
00541
00542
00543
00544 static void events_setup(struct Curl_multi *multi, struct events *ev)
00545 {
00546
00547 curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer);
00548 curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev);
00549
00550
00551 curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket);
00552 curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev);
00553 }
00554
00555
00556
00557
00558
00559
00560
00561 static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
00562 {
00563 bool done = FALSE;
00564 CURLMcode mcode;
00565 CURLcode result = CURLE_OK;
00566
00567 while(!done) {
00568 CURLMsg *msg;
00569 struct socketmonitor *m;
00570 struct pollfd *f;
00571 struct pollfd fds[4];
00572 int numfds=0;
00573 int pollrc;
00574 int i;
00575 struct timeval before;
00576 struct timeval after;
00577
00578
00579 for(m = ev->list, f=&fds[0]; m; m = m->next) {
00580 f->fd = m->socket.fd;
00581 f->events = m->socket.events;
00582 f->revents = 0;
00583
00584 f++;
00585 numfds++;
00586 }
00587
00588
00589 before = curlx_tvnow();
00590
00591
00592 pollrc = Curl_poll(fds, numfds, (int)ev->ms);
00593
00594 after = curlx_tvnow();
00595
00596 ev->msbump = FALSE;
00597
00598 if(0 == pollrc) {
00599
00600 ev->ms = 0;
00601
00602 mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
00603 &ev->running_handles);
00604 }
00605 else if(pollrc > 0) {
00606
00607 for(i = 0; i< numfds; i++) {
00608 if(fds[i].revents) {
00609
00610 int act = poll2cselect(fds[i].revents);
00611 infof(multi->easyp, "call curl_multi_socket_action(socket %d)\n",
00612 fds[i].fd);
00613 mcode = curl_multi_socket_action(multi, fds[i].fd, act,
00614 &ev->running_handles);
00615 }
00616 }
00617
00618 if(!ev->msbump)
00619
00620
00621
00622 ev->ms += curlx_tvdiff(after, before);
00623
00624 }
00625 else
00626 return CURLE_RECV_ERROR;
00627
00628 if(mcode)
00629 return CURLE_URL_MALFORMAT;
00630
00631
00632
00633 msg = curl_multi_info_read(multi, &pollrc);
00634 if(msg) {
00635 result = msg->data.result;
00636 done = TRUE;
00637 }
00638 }
00639
00640 return result;
00641 }
00642
00643
00644
00645
00646
00647
00648 static CURLcode easy_events(struct Curl_multi *multi)
00649 {
00650 struct events evs= {2, FALSE, 0, NULL, 0};
00651
00652
00653 events_setup(multi, &evs);
00654
00655 return wait_or_timeout(multi, &evs);
00656 }
00657 #else
00658
00659 #define easy_events(x) CURLE_NOT_BUILT_IN
00660 #endif
00661
00662 static CURLcode easy_transfer(struct Curl_multi *multi)
00663 {
00664 bool done = FALSE;
00665 CURLMcode mcode = CURLM_OK;
00666 CURLcode result = CURLE_OK;
00667 struct timeval before;
00668 int without_fds = 0;
00669
00670
00671 while(!done && !mcode) {
00672 int still_running = 0;
00673 int rc;
00674
00675 before = curlx_tvnow();
00676 mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc);
00677
00678 if(!mcode) {
00679 if(!rc) {
00680 struct timeval after = curlx_tvnow();
00681
00682
00683
00684
00685 if(curlx_tvdiff(after, before) <= 10) {
00686 without_fds++;
00687 if(without_fds > 2) {
00688 int sleep_ms = without_fds < 10 ? (1 << (without_fds - 1)) : 1000;
00689 Curl_wait_ms(sleep_ms);
00690 }
00691 }
00692 else
00693
00694 without_fds = 0;
00695 }
00696 else
00697
00698 without_fds = 0;
00699
00700 mcode = curl_multi_perform(multi, &still_running);
00701 }
00702
00703
00704 if(!mcode && !still_running) {
00705 CURLMsg *msg = curl_multi_info_read(multi, &rc);
00706 if(msg) {
00707 result = msg->data.result;
00708 done = TRUE;
00709 }
00710 }
00711 }
00712
00713
00714 if(mcode) {
00715 result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
00716
00717
00718 CURLE_BAD_FUNCTION_ARGUMENT;
00719 }
00720
00721 return result;
00722 }
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 static CURLcode easy_perform(struct Curl_easy *data, bool events)
00743 {
00744 struct Curl_multi *multi;
00745 CURLMcode mcode;
00746 CURLcode result = CURLE_OK;
00747 SIGPIPE_VARIABLE(pipe_st);
00748
00749 if(!data)
00750 return CURLE_BAD_FUNCTION_ARGUMENT;
00751
00752 if(data->multi) {
00753 failf(data, "easy handle already used in multi handle");
00754 return CURLE_FAILED_INIT;
00755 }
00756
00757 if(data->multi_easy)
00758 multi = data->multi_easy;
00759 else {
00760
00761
00762 multi = Curl_multi_handle(1, 3);
00763 if(!multi)
00764 return CURLE_OUT_OF_MEMORY;
00765 data->multi_easy = multi;
00766 }
00767
00768
00769 curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
00770
00771 mcode = curl_multi_add_handle(multi, data);
00772 if(mcode) {
00773 curl_multi_cleanup(multi);
00774 if(mcode == CURLM_OUT_OF_MEMORY)
00775 return CURLE_OUT_OF_MEMORY;
00776 else
00777 return CURLE_FAILED_INIT;
00778 }
00779
00780 sigpipe_ignore(data, &pipe_st);
00781
00782
00783
00784 data->multi = multi;
00785
00786
00787 result = events ? easy_events(multi) : easy_transfer(multi);
00788
00789
00790
00791 (void)curl_multi_remove_handle(multi, data);
00792
00793 sigpipe_restore(&pipe_st);
00794
00795
00796 return result;
00797 }
00798
00799
00800
00801
00802
00803
00804 CURLcode curl_easy_perform(struct Curl_easy *data)
00805 {
00806 return easy_perform(data, FALSE);
00807 }
00808
00809 #ifdef CURLDEBUG
00810
00811
00812
00813
00814 CURLcode curl_easy_perform_ev(struct Curl_easy *data)
00815 {
00816 return easy_perform(data, TRUE);
00817 }
00818
00819 #endif
00820
00821
00822
00823
00824
00825 void curl_easy_cleanup(struct Curl_easy *data)
00826 {
00827 SIGPIPE_VARIABLE(pipe_st);
00828
00829 if(!data)
00830 return;
00831
00832 sigpipe_ignore(data, &pipe_st);
00833 Curl_close(data);
00834 sigpipe_restore(&pipe_st);
00835 }
00836
00837
00838
00839
00840
00841 #undef curl_easy_getinfo
00842 CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...)
00843 {
00844 va_list arg;
00845 void *paramp;
00846 CURLcode result;
00847
00848 va_start(arg, info);
00849 paramp = va_arg(arg, void *);
00850
00851 result = Curl_getinfo(data, info, paramp);
00852
00853 va_end(arg);
00854 return result;
00855 }
00856
00857
00858
00859
00860
00861
00862 struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
00863 {
00864 struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy));
00865 if(NULL == outcurl)
00866 goto fail;
00867
00868
00869
00870
00871
00872
00873 outcurl->state.headerbuff = malloc(HEADERSIZE);
00874 if(!outcurl->state.headerbuff)
00875 goto fail;
00876 outcurl->state.headersize = HEADERSIZE;
00877
00878
00879 if(Curl_dupset(outcurl, data))
00880 goto fail;
00881
00882
00883 outcurl->state.conn_cache = NULL;
00884
00885 outcurl->state.lastconnect = NULL;
00886
00887 outcurl->progress.flags = data->progress.flags;
00888 outcurl->progress.callback = data->progress.callback;
00889
00890 if(data->cookies) {
00891
00892
00893 outcurl->cookies = Curl_cookie_init(data,
00894 data->cookies->filename,
00895 outcurl->cookies,
00896 data->set.cookiesession);
00897 if(!outcurl->cookies)
00898 goto fail;
00899 }
00900
00901
00902 if(data->change.cookielist) {
00903 outcurl->change.cookielist =
00904 Curl_slist_duplicate(data->change.cookielist);
00905 if(!outcurl->change.cookielist)
00906 goto fail;
00907 }
00908
00909 if(data->change.url) {
00910 outcurl->change.url = strdup(data->change.url);
00911 if(!outcurl->change.url)
00912 goto fail;
00913 outcurl->change.url_alloc = TRUE;
00914 }
00915
00916 if(data->change.referer) {
00917 outcurl->change.referer = strdup(data->change.referer);
00918 if(!outcurl->change.referer)
00919 goto fail;
00920 outcurl->change.referer_alloc = TRUE;
00921 }
00922
00923
00924 if(Curl_resolver_duphandle(&outcurl->state.resolver,
00925 data->state.resolver))
00926 goto fail;
00927
00928 Curl_convert_setup(outcurl);
00929
00930 Curl_initinfo(outcurl);
00931
00932 outcurl->magic = CURLEASY_MAGIC_NUMBER;
00933
00934
00935
00936 return outcurl;
00937
00938 fail:
00939
00940 if(outcurl) {
00941 curl_slist_free_all(outcurl->change.cookielist);
00942 outcurl->change.cookielist = NULL;
00943 Curl_safefree(outcurl->state.headerbuff);
00944 Curl_safefree(outcurl->change.url);
00945 Curl_safefree(outcurl->change.referer);
00946 Curl_freeset(outcurl);
00947 free(outcurl);
00948 }
00949
00950 return NULL;
00951 }
00952
00953
00954
00955
00956
00957 void curl_easy_reset(struct Curl_easy *data)
00958 {
00959 Curl_safefree(data->state.pathbuffer);
00960
00961 data->state.path = NULL;
00962
00963 Curl_free_request_state(data);
00964
00965
00966 Curl_freeset(data);
00967 memset(&data->set, 0, sizeof(struct UserDefined));
00968 (void)Curl_init_userdefined(&data->set);
00969
00970
00971 memset(&data->progress, 0, sizeof(struct Progress));
00972
00973
00974 Curl_initinfo(data);
00975
00976 data->progress.flags |= PGRS_HIDE;
00977 data->state.current_speed = -1;
00978 }
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990 CURLcode curl_easy_pause(struct Curl_easy *data, int action)
00991 {
00992 struct SingleRequest *k = &data->req;
00993 CURLcode result = CURLE_OK;
00994
00995
00996 int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
00997
00998
00999 newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
01000 ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
01001
01002
01003 k->keepon = newstate;
01004
01005 if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) {
01006
01007
01008
01009
01010
01011
01012 char *tempwrite = data->state.tempwrite;
01013
01014 data->state.tempwrite = NULL;
01015 result = Curl_client_chop_write(data->easy_conn, data->state.tempwritetype,
01016 tempwrite, data->state.tempwritesize);
01017 free(tempwrite);
01018 }
01019
01020
01021
01022 if(!result &&
01023 ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
01024 (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
01025 Curl_expire(data, 0);
01026
01027 return result;
01028 }
01029
01030
01031 static CURLcode easy_connection(struct Curl_easy *data,
01032 curl_socket_t *sfd,
01033 struct connectdata **connp)
01034 {
01035 if(data == NULL)
01036 return CURLE_BAD_FUNCTION_ARGUMENT;
01037
01038
01039 if(!data->set.connect_only) {
01040 failf(data, "CONNECT_ONLY is required!");
01041 return CURLE_UNSUPPORTED_PROTOCOL;
01042 }
01043
01044 *sfd = Curl_getconnectinfo(data, connp);
01045
01046 if(*sfd == CURL_SOCKET_BAD) {
01047 failf(data, "Failed to get recent socket");
01048 return CURLE_UNSUPPORTED_PROTOCOL;
01049 }
01050
01051 return CURLE_OK;
01052 }
01053
01054
01055
01056
01057
01058
01059 CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
01060 size_t *n)
01061 {
01062 curl_socket_t sfd;
01063 CURLcode result;
01064 ssize_t n1;
01065 struct connectdata *c;
01066
01067 result = easy_connection(data, &sfd, &c);
01068 if(result)
01069 return result;
01070
01071 *n = 0;
01072 result = Curl_read(c, sfd, buffer, buflen, &n1);
01073
01074 if(result)
01075 return result;
01076
01077 *n = (size_t)n1;
01078
01079 return CURLE_OK;
01080 }
01081
01082
01083
01084
01085
01086 CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
01087 size_t buflen, size_t *n)
01088 {
01089 curl_socket_t sfd;
01090 CURLcode result;
01091 ssize_t n1;
01092 struct connectdata *c = NULL;
01093
01094 result = easy_connection(data, &sfd, &c);
01095 if(result)
01096 return result;
01097
01098 *n = 0;
01099 result = Curl_write(c, sfd, buffer, buflen, &n1);
01100
01101 if(n1 == -1)
01102 return CURLE_SEND_ERROR;
01103
01104
01105 if(!result && !n1)
01106 return CURLE_AGAIN;
01107
01108 *n = (size_t)n1;
01109
01110 return result;
01111 }