/* Curl_client_write() sends data to the write callback(s) The bit pattern defines to what "streams" to write to. Body and/or header. The defines are in sendf.h of course. If CURL_DO_LINEEND_CONV is enabled, data is converted IN PLACE to the local character encoding. This is a problem and should be changed in the future to leave the original data alone. */ CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, size_t len) { struct SessionHandle *data = conn->data; if(0 == len) len = strlen(ptr); /* FTP data may need conversion. */ if((type & CLIENTWRITE_BODY) && (conn->handler->protocol & PROTO_FAMILY_FTP) && conn->proto.ftpc.transfertype == 'A') { /* convert from the network encoding */ CURLcode result = Curl_convert_from_network(data, ptr, len); /* Curl_convert_from_network calls failf if unsuccessful */ if(result) return result; #ifdef CURL_DO_LINEEND_CONV /* convert end-of-line markers */ len = convert_lineends(data, ptr, len); #endif /* CURL_DO_LINEEND_CONV */ } return Curl_client_chop_write(conn, type, ptr, len); }
/* * curl_easy_pause() allows an application to pause or unpause a specific * transfer and direction. This function sets the full new state for the * current connection this easy handle operates on. * * NOTE: if you have the receiving paused and you call this function to remove * the pausing, you may get your write callback called at this point. * * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h */ CURLcode curl_easy_pause(struct Curl_easy *data, int action) { struct SingleRequest *k = &data->req; CURLcode result = CURLE_OK; /* first switch off both pause bits */ int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE); /* set the new desired pause bits */ newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) | ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0); /* put it back in the keepon */ k->keepon = newstate; if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempcount) { /* there are buffers for sending that can be delivered as the receive pausing is lifted! */ unsigned int i; unsigned int count = data->state.tempcount; struct tempbuf writebuf[3]; /* there can only be three */ /* copy the structs to allow for immediate re-pausing */ for(i=0; i < data->state.tempcount; i++) { writebuf[i] = data->state.tempwrite[i]; data->state.tempwrite[i].buf = NULL; } data->state.tempcount = 0; for(i=0; i < count; i++) { /* even if one function returns error, this loops through and frees all buffers */ if(!result) result = Curl_client_chop_write(data->easy_conn, writebuf[i].type, writebuf[i].buf, writebuf[i].len); free(writebuf[i].buf); } if(result) return result; } /* if there's no error and we're not pausing both directions, we want to have this handle checked soon */ if(!result && ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) != (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) ) Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */ return result; }
/* * curl_easy_pause() allows an application to pause or unpause a specific * transfer and direction. This function sets the full new state for the * current connection this easy handle operates on. * * NOTE: if you have the receiving paused and you call this function to remove * the pausing, you may get your write callback called at this point. * * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h */ CURLcode curl_easy_pause(CURL *curl, int action) { struct SessionHandle *data = (struct SessionHandle *)curl; struct SingleRequest *k = &data->req; CURLcode result = CURLE_OK; /* first switch off both pause bits */ int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE); /* set the new desired pause bits */ newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) | ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0); /* put it back in the keepon */ k->keepon = newstate; if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) { /* we have a buffer for sending that we now seem to be able to deliver since the receive pausing is lifted! */ /* get the pointer in local copy since the function may return PAUSE again and then we'll get a new copy allocted and stored in the tempwrite variables */ char *tempwrite = data->state.tempwrite; data->state.tempwrite = NULL; result = Curl_client_chop_write(data->easy_conn, data->state.tempwritetype, tempwrite, data->state.tempwritesize); free(tempwrite); } /* if there's no error and we're not pausing both directions, we want to have this handle checked soon */ if(!result && ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) != (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) ) Curl_expire(data, 1); /* get this handle going again */ return result; }