1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
26 * See comment in curl_memory.h for the explanation of this sanity check.
29 #ifdef CURLX_NO_MEMORY_CALLBACKS
30 #error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined"
33 #ifdef HAVE_NETINET_IN_H
34 #include <netinet/in.h>
39 #ifdef HAVE_ARPA_INET_H
40 #include <arpa/inet.h>
45 #ifdef HAVE_SYS_IOCTL_H
46 #include <sys/ioctl.h>
49 #ifdef HAVE_SYS_PARAM_H
50 #include <sys/param.h>
55 #include <curl/curl.h>
57 #include "vtls/vtls.h"
63 #include "curl_memory.h"
67 #include "sendf.h" /* for failf function prototype */
68 #include "curl_ntlm.h"
69 #include "connect.h" /* for Curl_getconnectinfo */
72 #include "non-ascii.h"
74 #include "conncache.h"
78 #define _MPRINTF_REPLACE /* use our functions only */
79 #include <curl/mprintf.h>
81 /* The last #include file should be: */
84 /* win32_cleanup() is for win32 socket cleanup functionality, the opposite
86 static void win32_cleanup(void)
91 #ifdef USE_WINDOWS_SSPI
92 Curl_sspi_global_cleanup();
96 /* win32_init() performs win32 socket initialization to properly setup the
97 stack to allow networking */
98 static CURLcode win32_init(void)
101 WORD wVersionRequested;
105 #if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
106 Error IPV6_requires_winsock2
109 wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
111 res = WSAStartup(wVersionRequested, &wsaData);
114 /* Tell the user that we couldn't find a useable */
116 return CURLE_FAILED_INIT;
118 /* Confirm that the Windows Sockets DLL supports what we need.*/
119 /* Note that if the DLL supports versions greater */
120 /* than wVersionRequested, it will still return */
121 /* wVersionRequested in wVersion. wHighVersion contains the */
122 /* highest supported version. */
124 if(LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
125 HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
126 /* Tell the user that we couldn't find a useable */
130 return CURLE_FAILED_INIT;
132 /* The Windows Sockets DLL is acceptable. Proceed. */
133 #elif defined(USE_LWIPSOCK)
137 #ifdef USE_WINDOWS_SSPI
139 CURLcode err = Curl_sspi_global_init();
150 * Initialise use of IDNA library.
151 * It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
152 * idna_to_ascii_lz().
154 static void idna_init (void)
160 if(!getenv("CHARSET") && cp > 0) {
161 snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
168 #endif /* USE_LIBIDN */
170 /* true globals -- for curl_global_init() and curl_global_cleanup() */
171 static unsigned int initialized;
172 static long init_flags;
175 * strdup (and other memory functions) is redefined in complicated
176 * ways, but at this point it must be defined as the system-supplied strdup
177 * so the callback pointer is initialized correctly.
179 #if defined(_WIN32_WCE)
180 #define system_strdup _strdup
181 #elif !defined(HAVE_STRDUP)
182 #define system_strdup curlx_strdup
184 #define system_strdup strdup
187 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
188 # pragma warning(disable:4232) /* MSVC extension, dllimport identity */
191 #ifndef __SYMBIAN32__
193 * If a memory-using function (like curl_getenv) is used before
194 * curl_global_init() is called, we need to have these pointers set already.
196 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
197 curl_free_callback Curl_cfree = (curl_free_callback)free;
198 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
199 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
200 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
201 #if defined(WIN32) && defined(UNICODE)
202 curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
206 * Symbian OS doesn't support initialization to code in writeable static data.
207 * Initialization will occur in the curl_global_init() call.
209 curl_malloc_callback Curl_cmalloc;
210 curl_free_callback Curl_cfree;
211 curl_realloc_callback Curl_crealloc;
212 curl_strdup_callback Curl_cstrdup;
213 curl_calloc_callback Curl_ccalloc;
216 #if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__)
217 # pragma warning(default:4232) /* MSVC extension, dllimport identity */
221 * curl_global_init() globally initializes cURL given a bitwise set of the
222 * different features of what to initialize.
224 CURLcode curl_global_init(long flags)
229 /* Setup the default memory functions here (again) */
230 Curl_cmalloc = (curl_malloc_callback)malloc;
231 Curl_cfree = (curl_free_callback)free;
232 Curl_crealloc = (curl_realloc_callback)realloc;
233 Curl_cstrdup = (curl_strdup_callback)system_strdup;
234 Curl_ccalloc = (curl_calloc_callback)calloc;
235 #if defined(WIN32) && defined(UNICODE)
236 Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
239 if(flags & CURL_GLOBAL_SSL)
240 if(!Curl_ssl_init()) {
241 DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
242 return CURLE_FAILED_INIT;
245 if(flags & CURL_GLOBAL_WIN32)
246 if(win32_init() != CURLE_OK) {
247 DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
248 return CURLE_FAILED_INIT;
252 if(!Curl_amiga_init()) {
253 DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
254 return CURLE_FAILED_INIT;
260 DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n"));
268 if(Curl_resolver_global_init() != CURLE_OK) {
269 DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
270 return CURLE_FAILED_INIT;
273 #if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT)
274 if(libssh2_init(0)) {
275 DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
276 return CURLE_FAILED_INIT;
280 if(flags & CURL_GLOBAL_ACK_EINTR)
289 * curl_global_init_mem() globally initializes cURL and also registers the
290 * user provided callback routines.
292 CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
293 curl_free_callback f, curl_realloc_callback r,
294 curl_strdup_callback s, curl_calloc_callback c)
296 CURLcode code = CURLE_OK;
298 /* Invalid input, return immediately */
299 if(!m || !f || !r || !s || !c)
300 return CURLE_FAILED_INIT;
303 /* Already initialized, don't do it again, but bump the variable anyway to
304 work like curl_global_init() and require the same amount of cleanup
310 /* Call the actual init function first */
311 code = curl_global_init(flags);
312 if(code == CURLE_OK) {
324 * curl_global_cleanup() globally cleanups cURL, uses the value of
325 * "init_flags" to determine what needs to be cleaned up and what doesn't.
327 void curl_global_cleanup(void)
335 Curl_global_host_cache_dtor();
337 if(init_flags & CURL_GLOBAL_SSL)
340 Curl_resolver_global_cleanup();
342 if(init_flags & CURL_GLOBAL_WIN32)
345 Curl_amiga_cleanup();
347 #if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT)
348 (void)libssh2_exit();
355 * curl_easy_init() is the external interface to alloc, setup and init an
356 * easy handle that is returned. If anything goes wrong, NULL is returned.
358 CURL *curl_easy_init(void)
361 struct SessionHandle *data;
363 /* Make sure we inited the global SSL stuff */
365 res = curl_global_init(CURL_GLOBAL_DEFAULT);
367 /* something in the global init failed, return nothing */
368 DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
373 /* We use curl_open() with undefined URL so far */
374 res = Curl_open(&data);
375 if(res != CURLE_OK) {
376 DEBUGF(fprintf(stderr, "Error: Curl_open failed\n"));
384 * curl_easy_setopt() is the external interface for setting options on an
388 #undef curl_easy_setopt
389 CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
392 struct SessionHandle *data = curl;
396 return CURLE_BAD_FUNCTION_ARGUMENT;
400 ret = Curl_setopt(data, tag, arg);
408 struct socketmonitor {
409 struct socketmonitor *next; /* the next node in the list or NULL */
410 struct pollfd socket; /* socket info of what to monitor */
414 long ms; /* timeout, run the timeout function when reached */
415 bool msbump; /* set TRUE when timeout is set by callback */
416 int num_sockets; /* number of nodes in the monitor list */
417 struct socketmonitor *list; /* list of sockets to monitor */
418 int running_handles; /* store the returned number */
423 * Callback that gets called with a new value when the timeout should be
427 static int events_timer(CURLM *multi, /* multi handle */
428 long timeout_ms, /* see above */
429 void *userp) /* private callback pointer */
431 struct events *ev = userp;
434 /* timeout removed */
436 else if(timeout_ms == 0)
437 /* timeout is already reached! */
438 timeout_ms = 1; /* trigger asap */
448 * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones
450 static int poll2cselect(int pollmask)
453 if(pollmask & POLLIN)
454 omask |= CURL_CSELECT_IN;
455 if(pollmask & POLLOUT)
456 omask |= CURL_CSELECT_OUT;
457 if(pollmask & POLLERR)
458 omask |= CURL_CSELECT_ERR;
465 * convert from libcurl' CURL_POLL_* bit definitions to poll()'s
467 static short socketcb2poll(int pollmask)
470 if(pollmask & CURL_POLL_IN)
472 if(pollmask & CURL_POLL_OUT)
479 * Callback that gets called with information about socket activity to
482 static int events_socket(CURL *easy, /* easy handle */
483 curl_socket_t s, /* socket */
484 int what, /* see above */
485 void *userp, /* private callback
487 void *socketp) /* private socket
490 struct events *ev = userp;
491 struct socketmonitor *m;
492 struct socketmonitor *prev=NULL;
497 if(m->socket.fd == s) {
499 if(what == CURL_POLL_REMOVE) {
500 struct socketmonitor *nxt = m->next;
501 /* remove this node from the list of monitored sockets */
508 infof(easy, "socket cb: socket %d REMOVED\n", s);
511 /* The socket 's' is already being monitored, update the activity
512 mask. Convert from libcurl bitmask to the poll one. */
513 m->socket.events = socketcb2poll(what);
514 infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
515 what&CURL_POLL_IN?"IN":"",
516 what&CURL_POLL_OUT?"OUT":"");
521 m = m->next; /* move to next node */
524 if(what == CURL_POLL_REMOVE) {
525 /* this happens a bit too often, libcurl fix perhaps? */
527 "%s: socket %d asked to be REMOVED but not present!\n",
531 m = malloc(sizeof(struct socketmonitor));
534 m->socket.events = socketcb2poll(what);
535 m->socket.revents = 0;
537 infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
538 what&CURL_POLL_IN?"IN":"",
539 what&CURL_POLL_OUT?"OUT":"");
550 * Do the multi handle setups that only event-based transfers need.
552 static void events_setup(CURLM *multi, struct events *ev)
555 curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer);
556 curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev);
558 /* socket callback */
559 curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket);
560 curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev);
566 * waits for activity on any of the given sockets, or the timeout to trigger.
569 static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
573 CURLcode rc = CURLE_OK;
577 struct socketmonitor *m;
579 struct pollfd fds[4];
583 struct timeval before;
584 struct timeval after;
586 /* populate the fds[] array */
587 for(m = ev->list, f=&fds[0]; m; m = m->next) {
588 f->fd = m->socket.fd;
589 f->events = m->socket.events;
591 /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */
596 /* get the time stamp to use to figure out how long poll takes */
597 before = curlx_tvnow();
599 /* wait for activity or timeout */
600 pollrc = Curl_poll(fds, numfds, (int)ev->ms);
602 after = curlx_tvnow();
604 ev->msbump = FALSE; /* reset here */
609 /* fprintf(stderr, "call curl_multi_socket_action( TIMEOUT )\n"); */
610 mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0,
611 &ev->running_handles);
613 else if(pollrc > 0) {
614 /* loop over the monitored sockets to see which ones had activity */
615 for(i = 0; i< numfds; i++) {
617 /* socket activity, tell libcurl */
618 int act = poll2cselect(fds[i].revents); /* convert */
619 infof(multi->easyp, "call curl_multi_socket_action( socket %d )\n",
621 mcode = curl_multi_socket_action(multi, fds[i].fd, act,
622 &ev->running_handles);
627 /* If nothing updated the timeout, we decrease it by the spent time.
628 * If it was updated, it has the new timeout time stored already.
630 ev->ms += curlx_tvdiff(after, before);
634 return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */
636 /* we don't really care about the "msgs_in_queue" value returned in the
638 msg = curl_multi_info_read(multi, &pollrc);
640 rc = msg->data.result;
651 * Runs a transfer in a blocking manner using the events-based API
653 static CURLcode easy_events(CURLM *multi)
655 struct events evs= {2, FALSE, 0, NULL, 0};
657 /* if running event-based, do some further multi inits */
658 events_setup(multi, &evs);
660 return wait_or_timeout(multi, &evs);
662 #else /* CURLDEBUG */
663 /* when not built with debug, this function doesn't exist */
664 #define easy_events(x) CURLE_NOT_BUILT_IN
667 static CURLcode easy_transfer(CURLM *multi)
670 CURLMcode mcode = CURLM_OK;
671 CURLcode code = CURLE_OK;
672 struct timeval before;
673 int without_fds = 0; /* count number of consecutive returns from
674 curl_multi_wait() without any filedescriptors */
676 while(!done && !mcode) {
677 int still_running = 0;
680 before = curlx_tvnow();
681 mcode = curl_multi_wait(multi, NULL, 0, 1000, &ret);
683 if(mcode == CURLM_OK) {
685 /* poll() failed not on EINTR, indicate a network problem */
686 code = CURLE_RECV_ERROR;
690 struct timeval after = curlx_tvnow();
691 /* If it returns without any filedescriptor instantly, we need to
692 avoid busy-looping during periods where it has nothing particular
694 if(curlx_tvdiff(after, before) <= 10) {
696 if(without_fds > 2) {
697 int sleep_ms = without_fds < 10 ? (1 << (without_fds-1)): 1000;
698 Curl_wait_ms(sleep_ms);
702 /* it wasn't "instant", restart counter */
706 /* got file descriptor, restart counter */
709 mcode = curl_multi_perform(multi, &still_running);
712 /* only read 'still_running' if curl_multi_perform() return OK */
713 if((mcode == CURLM_OK) && !still_running) {
715 CURLMsg *msg = curl_multi_info_read(multi, &rc);
717 code = msg->data.result;
723 /* Make sure to return some kind of error if there was a multi problem */
725 return (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY :
726 /* The other multi errors should never happen, so return
727 something suitably generic */
728 CURLE_BAD_FUNCTION_ARGUMENT;
736 * easy_perform() is the external interface that performs a blocking
737 * transfer as previously setup.
739 * CONCEPT: This function creates a multi handle, adds the easy handle to it,
740 * runs curl_multi_perform() until the transfer is done, then detaches the
741 * easy handle, destroys the multi handle and returns the easy handle's return
744 * REALITY: it can't just create and destroy the multi handle that easily. It
745 * needs to keep it around since if this easy handle is used again by this
746 * function, the same multi handle must be re-used so that the same pools and
747 * caches can be used.
749 * DEBUG: if 'events' is set TRUE, this function will use a replacement engine
750 * instead of curl_multi_perform() and use curl_multi_socket_action().
752 static CURLcode easy_perform(struct SessionHandle *data, bool events)
756 CURLcode code = CURLE_OK;
757 SIGPIPE_VARIABLE(pipe_st);
760 return CURLE_BAD_FUNCTION_ARGUMENT;
763 failf(data, "easy handle already used in multi handle");
764 return CURLE_FAILED_INIT;
768 multi = data->multi_easy;
770 /* this multi handle will only ever have a single easy handled attached
771 to it, so make it use minimal hashes */
772 multi = Curl_multi_handle(1, 3);
774 return CURLE_OUT_OF_MEMORY;
775 data->multi_easy = multi;
778 /* Copy the MAXCONNECTS option to the multi handle */
779 curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
781 mcode = curl_multi_add_handle(multi, data);
783 curl_multi_cleanup(multi);
784 if(mcode == CURLM_OUT_OF_MEMORY)
785 return CURLE_OUT_OF_MEMORY;
787 return CURLE_FAILED_INIT;
790 sigpipe_ignore(data, &pipe_st);
792 /* assign this after curl_multi_add_handle() since that function checks for
793 it and rejects this handle otherwise */
796 /* run the transfer */
797 code = events ? easy_events(multi) : easy_transfer(multi);
799 /* ignoring the return code isn't nice, but atm we can't really handle
800 a failure here, room for future improvement! */
801 (void)curl_multi_remove_handle(multi, data);
803 sigpipe_restore(&pipe_st);
805 /* The multi handle is kept alive, owned by the easy handle */
811 * curl_easy_perform() is the external interface that performs a blocking
812 * transfer as previously setup.
814 CURLcode curl_easy_perform(CURL *easy)
816 return easy_perform(easy, FALSE);
821 * curl_easy_perform_ev() is the external interface that performs a blocking
822 * transfer using the event-based API internally.
824 CURLcode curl_easy_perform_ev(CURL *easy)
826 return easy_perform(easy, TRUE);
832 * curl_easy_cleanup() is the external interface to cleaning/freeing the given
835 void curl_easy_cleanup(CURL *curl)
837 struct SessionHandle *data = (struct SessionHandle *)curl;
838 SIGPIPE_VARIABLE(pipe_st);
843 sigpipe_ignore(data, &pipe_st);
845 sigpipe_restore(&pipe_st);
849 * curl_easy_getinfo() is an external interface that allows an app to retrieve
850 * information from a performed transfer and similar.
852 #undef curl_easy_getinfo
853 CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
858 struct SessionHandle *data = (struct SessionHandle *)curl;
861 paramp = va_arg(arg, void *);
863 ret = Curl_getinfo(data, info, paramp);
870 * curl_easy_duphandle() is an external interface to allow duplication of a
871 * given input easy handle. The returned handle will be a new working handle
872 * with all options set exactly as the input source handle.
874 CURL *curl_easy_duphandle(CURL *incurl)
876 struct SessionHandle *data=(struct SessionHandle *)incurl;
878 struct SessionHandle *outcurl = calloc(1, sizeof(struct SessionHandle));
883 * We setup a few buffers we need. We should probably make them
884 * get setup on-demand in the code, as that would probably decrease
885 * the likeliness of us forgetting to init a buffer here in the future.
887 outcurl->state.headerbuff = malloc(HEADERSIZE);
888 if(!outcurl->state.headerbuff)
890 outcurl->state.headersize = HEADERSIZE;
892 /* copy all userdefined values */
893 if(Curl_dupset(outcurl, data) != CURLE_OK)
896 /* the connection cache is setup on demand */
897 outcurl->state.conn_cache = NULL;
899 outcurl->state.lastconnect = NULL;
901 outcurl->progress.flags = data->progress.flags;
902 outcurl->progress.callback = data->progress.callback;
905 /* If cookies are enabled in the parent handle, we enable them
906 in the clone as well! */
907 outcurl->cookies = Curl_cookie_init(data,
908 data->cookies->filename,
910 data->set.cookiesession);
911 if(!outcurl->cookies)
915 /* duplicate all values in 'change' */
916 if(data->change.cookielist) {
917 outcurl->change.cookielist =
918 Curl_slist_duplicate(data->change.cookielist);
919 if(!outcurl->change.cookielist)
923 if(data->change.url) {
924 outcurl->change.url = strdup(data->change.url);
925 if(!outcurl->change.url)
927 outcurl->change.url_alloc = TRUE;
930 if(data->change.referer) {
931 outcurl->change.referer = strdup(data->change.referer);
932 if(!outcurl->change.referer)
934 outcurl->change.referer_alloc = TRUE;
937 /* Clone the resolver handle, if present, for the new handle */
938 if(Curl_resolver_duphandle(&outcurl->state.resolver,
939 data->state.resolver) != CURLE_OK)
942 Curl_convert_setup(outcurl);
944 outcurl->magic = CURLEASY_MAGIC_NUMBER;
946 /* we reach this point and thus we are OK */
953 curl_slist_free_all(outcurl->change.cookielist);
954 outcurl->change.cookielist = NULL;
955 Curl_safefree(outcurl->state.headerbuff);
956 Curl_safefree(outcurl->change.url);
957 Curl_safefree(outcurl->change.referer);
958 Curl_freeset(outcurl);
966 * curl_easy_reset() is an external interface that allows an app to re-
967 * initialize a session handle to the default values.
969 void curl_easy_reset(CURL *curl)
971 struct SessionHandle *data = (struct SessionHandle *)curl;
973 Curl_safefree(data->state.pathbuffer);
975 data->state.path = NULL;
977 Curl_free_request_state(data);
979 /* zero out UserDefined data: */
981 memset(&data->set, 0, sizeof(struct UserDefined));
982 (void)Curl_init_userdefined(&data->set);
984 /* zero out Progress data: */
985 memset(&data->progress, 0, sizeof(struct Progress));
987 data->progress.flags |= PGRS_HIDE;
988 data->state.current_speed = -1; /* init to negative == impossible */
992 * curl_easy_pause() allows an application to pause or unpause a specific
993 * transfer and direction. This function sets the full new state for the
994 * current connection this easy handle operates on.
996 * NOTE: if you have the receiving paused and you call this function to remove
997 * the pausing, you may get your write callback called at this point.
999 * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
1001 CURLcode curl_easy_pause(CURL *curl, int action)
1003 struct SessionHandle *data = (struct SessionHandle *)curl;
1004 struct SingleRequest *k = &data->req;
1005 CURLcode result = CURLE_OK;
1007 /* first switch off both pause bits */
1008 int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
1010 /* set the new desired pause bits */
1011 newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
1012 ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
1014 /* put it back in the keepon */
1015 k->keepon = newstate;
1017 if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) {
1018 /* we have a buffer for sending that we now seem to be able to deliver
1019 since the receive pausing is lifted! */
1021 /* get the pointer, type and length in local copies since the function may
1022 return PAUSE again and then we'll get a new copy allocted and stored in
1023 the tempwrite variables */
1024 char *tempwrite = data->state.tempwrite;
1025 char *freewrite = tempwrite; /* store this pointer to free it later */
1026 size_t tempsize = data->state.tempwritesize;
1027 int temptype = data->state.tempwritetype;
1030 /* clear tempwrite here just to make sure it gets cleared if there's no
1031 further use of it, and make sure we don't clear it after the function
1032 invoke as it may have been set to a new value by then */
1033 data->state.tempwrite = NULL;
1035 /* since the write callback API is define to never exceed
1036 CURL_MAX_WRITE_SIZE bytes in a single call, and since we may in fact
1037 have more data than that in our buffer here, we must loop sending the
1038 data in multiple calls until there's no data left or we get another
1041 A tricky part is that the function we call will "buffer" the data
1042 itself when it pauses on a particular buffer, so we may need to do some
1043 extra trickery if we get a pause return here.
1046 chunklen = (tempsize > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:tempsize;
1048 result = Curl_client_write(data->easy_conn,
1049 temptype, tempwrite, chunklen);
1051 /* failures abort the loop at once */
1054 if(data->state.tempwrite && (tempsize - chunklen)) {
1055 /* Ouch, the reading is again paused and the block we send is now
1056 "cached". If this is the final chunk we can leave it like this, but
1057 if we have more chunks that are cached after this, we need to free
1058 the newly cached one and put back a version that is truly the entire
1059 contents that is saved for later
1063 /* note that tempsize is still the size as before the callback was
1064 used, and thus the whole piece of data to keep */
1065 newptr = realloc(data->state.tempwrite, tempsize);
1068 free(data->state.tempwrite); /* free old area */
1069 data->state.tempwrite = NULL;
1070 result = CURLE_OUT_OF_MEMORY;
1071 /* tempwrite will be freed further down */
1074 data->state.tempwrite = newptr; /* store new pointer */
1075 memcpy(newptr, tempwrite, tempsize);
1076 data->state.tempwritesize = tempsize; /* store new size */
1077 /* tempwrite will be freed further down */
1078 break; /* go back to pausing until further notice */
1081 tempsize -= chunklen; /* left after the call above */
1082 tempwrite += chunklen; /* advance the pointer */
1085 } while((result == CURLE_OK) && tempsize);
1087 free(freewrite); /* this is unconditionally no longer used */
1090 /* if there's no error and we're not pausing both directions, we want
1091 to have this handle checked soon */
1093 ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
1094 (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
1095 Curl_expire(data, 1); /* get this handle going again */
1101 static CURLcode easy_connection(struct SessionHandle *data,
1103 struct connectdata **connp)
1106 return CURLE_BAD_FUNCTION_ARGUMENT;
1108 /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */
1109 if(!data->set.connect_only) {
1110 failf(data, "CONNECT_ONLY is required!");
1111 return CURLE_UNSUPPORTED_PROTOCOL;
1114 *sfd = Curl_getconnectinfo(data, connp);
1116 if(*sfd == CURL_SOCKET_BAD) {
1117 failf(data, "Failed to get recent socket");
1118 return CURLE_UNSUPPORTED_PROTOCOL;
1125 * Receives data from the connected socket. Use after successful
1126 * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1127 * Returns CURLE_OK on success, error code on error.
1129 CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
1134 struct connectdata *c;
1135 struct SessionHandle *data = (struct SessionHandle *)curl;
1137 ret = easy_connection(data, &sfd, &c);
1142 ret = Curl_read(c, sfd, buffer, buflen, &n1);
1153 * Sends data over the connected socket. Use after successful
1154 * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1156 CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen,
1162 struct connectdata *c = NULL;
1163 struct SessionHandle *data = (struct SessionHandle *)curl;
1165 ret = easy_connection(data, &sfd, &c);
1170 ret = Curl_write(c, sfd, buffer, buflen, &n1);
1173 return CURLE_SEND_ERROR;
1176 if((CURLE_OK == ret) && (0 == n1))