curl / Mailing Lists / curl-library / Single Mail

curl-library

A string issue that after received the http 204, the curl_formadd function seems couldn't work again

From: 杨俊 <yangjun9772_at_gmail.com>
Date: Mon, 16 Jan 2017 18:35:31 +0800

Hi guys,

Currently, I used the libcurl7.51.0+openssl+nghttp2 to do my work.
I used the multi_handles and curl_formadd.
When the demo do a POST and get a http 200 result, then I can do a POST
again and again.
(the POST message need the curl_formadd)
But if the demo get the http 204 result after the POST, then I can't do the
POST again.
It seemed that the POST's message can't be upload(the curl_formadd seems
didn't work).
Please help.
---------------------this is my code
snippet---------------------------------------
static void curl_ping_cfg(CURL *curl, struct curl_slist *head, char *auth)
{
CURLcode res;

/* set the opt */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0 );
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_CAINFO, "/tmp/cacert.pem");

/* set the head */
head = curl_slist_append(head , DEL_HTTPHEAD_ACCEPT);
head = curl_slist_append(head , "Path: /ping");
head = curl_slist_append(head , auth);
head = curl_slist_append(head , "Host: avs-alexa-na.amazon.com");
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, head);
if (res != CURLE_OK){
printf("%s: curl_easy_setopt failed: %s\n", __FUNCTION__,
curl_easy_strerror(res));
}

/* set the url */
curl_easy_setopt(curl, CURLOPT_URL, "https://avs-alexa-na.amazon.com/ping");

/* set the GET */
// curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);

}

static void curl_sync_state(CURL *curl, char *strJSONout,
 struct curl_httppost *postFirst,
 struct curl_httppost *postLast)
{

printf("%s\n%ld\n", strJSONout, strlen(strJSONout));

/* curl set the formadd */
/* JSON */
curl_formadd(&postFirst, &postLast,
CURLFORM_COPYNAME, "metadata", /* CURLFORM_PTRCONTENTS, pAlexaJSON, */
CURLFORM_COPYCONTENTS, strJSONout,
CURLFORM_CONTENTTYPE, "application/json; charset=UTF-8",
CURLFORM_END);

/* set http post */
curl_easy_setopt(curl, CURLOPT_HTTPPOST, postFirst);

}

static void curl_send_audio_content(CURL *curl, char *strJSONout,
struct curl_httppost *postFirst,
struct curl_httppost *postLast)
{

printf("%s\n%ld\n", strJSONout, strlen(strJSONout));

/* formadd */

//============josn================//
curl_formadd(&postFirst, &postLast,
CURLFORM_COPYNAME, "metadata", /* CURLFORM_PTRCONTENTS, pAlexaJSON, */
CURLFORM_COPYCONTENTS, strJSONout,
CURLFORM_CONTENTTYPE, "application/json; charset=UTF-8",
CURLFORM_END);

//=============Audio=================//
curl_formadd(&postFirst, &postLast,
CURLFORM_COPYNAME, "audio",
CURLFORM_STREAM, &micRing,
CURLFORM_CONTENTTYPE, "application/octet-stream", //"audio/L16; rate=16000;
channels=1",
CURLFORM_END);

/* set http post */
curl_easy_setopt(curl, CURLOPT_HTTPPOST, postFirst);

}

static void curl_send_audio_cfg(CURL *curl, struct curl_slist *head, char
*auth)
{
/* set the opt */
curl_easy_setopt(curl , CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl , CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0 );
curl_easy_setopt(curl , CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl , CURLOPT_CAINFO, "/tmp/cacert.pem");

/* set the head */
head = curl_slist_append(head , DEL_HTTPHEAD_ACCEPT);
head = curl_slist_append(head , DEL_HTTPHEAD_EXPECT);
head = curl_slist_append(head , "Path: /v20160207/events");
head = curl_slist_append(head , auth);
head = curl_slist_append(head , "Content-type: multipart/form-data" );
head = curl_slist_append(head , "Transfer-Encoding: chunked");
head = curl_slist_append(head , "Host: avs-alexa-na.amazon.com");

/* set the url */
curl_easy_setopt(curl, CURLOPT_URL, "
https://avs-alexa-na.amazon.com/v20160207/events");//v20160207/events
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, head);

curl_easy_setopt(curl, CURLOPT_READFUNCTION,
readFileFunc);////////////////////////////////设置读文件函数接口
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, WriteMemoryCallback);
 //CURLOPT_WRITEFUNCTION 将后继的动作交给write_data函数处理
curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void *)&headChunk);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_send_audio_callback);
 //CURLOPT_WRITEFUNCTION 将后继的动作交给write_data函数处理
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&mp3Ring);

}

static void curl_downchannel_cfg(CURL *curl, struct curl_slist *head, char
*auth)
{
CURLcode res;

/* set the opt */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_CAINFO, "/tmp/cacert.pem");

/* set the head */
head = curl_slist_append(head , DEL_HTTPHEAD_ACCEPT);
head = curl_slist_append(head , "Path: /v20160207/directives");
head = curl_slist_append(head , auth);
head = curl_slist_append(head , "Host: avs-alexa-na.amazon.com");
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, head);
if (res != CURLE_OK){
printf("%s: curl_easy_setopt failed: %s\n",
__FUNCTION__,curl_easy_strerror(res));
}

/* set the url */
curl_easy_setopt(curl, CURLOPT_URL, "
https://avs-alexa-na.amazon.com/v20160207/directives");

/* send all data to this function */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);

/* we pass our 'chunk' struct to the callback function */
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
}

void thread_task2(void)
{
int ret = 0;

/* the curl variable */
CURL *handles[HANDLECOUNT];
CURLM *multi_handle;
int i;
int still_running; /* keep number of running handles */
CURLMsg *msg; /* for picking up messages with the transfer status */
int msgs_left; /* how many messages are left */
char Authorization[1024] = "Authorization:Bearer ";
/* for the event variable */
char *strJSONout = NULL;
struct curl_httppost *postFirst = NULL, *postLast = NULL;
struct curl_slist *downHead = NULL;
struct curl_slist *pingHead = NULL;
struct curl_slist *eventHead = NULL;

/* start */
strcat( Authorization, atoken );
printf( "%s\nstarting ...\n", Authorization );
netState = NET_STATE_IDLE;

/* initialize time */
gettimeofday(&now , NULL);
pre=now;

/* initialize curl */
/* init a multi stack */
multi_handle = curl_multi_init();
/* Allocate one CURL handle per transfer */
for(i=0; i<HANDLECOUNT; i++){
handles[i] = curl_easy_init();
}

/*******************set the eventhandle opt******************/
curl_send_audio_cfg(handles[EVENT_HANDLE], eventHead, Authorization);

/*******************set the downchannel opt*******************/
chunk.memory = malloc(1); /* will be grown as needed by the realloc above
*/
chunk.size = 0; /* no data at this point */
curl_downchannel_cfg(handles[DOWN_HANDLE], downHead, Authorization);
curl_multi_add_handle(multi_handle, handles[DOWN_HANDLE]);

/******************set the ping opt***************************/
curl_ping_cfg(handles[PING_HANDLE], pingHead, Authorization);
curl_multi_add_handle(multi_handle, handles[PING_HANDLE]);

/********************run***************************************/
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
/* We do HTTP/2 so let's stick to one connection per host */
curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS, 1L);
/* we start some action by calling perform right away */
curl_multi_perform(multi_handle, &still_running);

do
{
struct timeval timeout;
int rc;/* select() return code */
CURLMcode mc; /* curl_multi_fdset() return code */

fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd = -1;

long curl_timeo = -1;

switch (netState)
{
case NET_STATE_PING:
{
if (!eventFlag){
printf("start ping ~~~~~~~~~~~\n");
curl_multi_add_handle(multi_handle, handles[PING_HANDLE]);
pingFlag = 1;
netState = NET_STATE_IDLE;
}
}
break;
case NET_STATE_SEND_STATE:
{
headChunk.memory = malloc(1);
headChunk.size = 0;
mp3Ring.frameSize = 1;
mp3Ring.ringLength = 48*1024;
mp3Ring.rxCache = 0;
init_ring_buffer(&mp3Ring);
curl_sync_state(handles[EVENT_HANDLE], strJSONout, postFirst, postLast);
curl_multi_add_handle(multi_handle, handles[EVENT_HANDLE]);
printf("start send the state ~~~~~~\n");
netState = NET_STATE_IDLE;
}
break;
case NET_STATE_SEND_EVENT:
{
if (!pingFlag){
eventFlag = 1;
headChunk.memory = malloc(1);
headChunk.size = 0;
mp3Ring.frameSize = 1;
mp3Ring.ringLength = 48*1024;
mp3Ring.rxCache = 0;
init_ring_buffer(&mp3Ring);
curl_send_audio_content(handles[EVENT_HANDLE], strJSONout, postFirst,
postLast);
curl_multi_add_handle(multi_handle, handles[EVENT_HANDLE]);
printf("start event ~~~~~~~~~~~~~\n");
netState = NET_STATE_IDLE;
}
}
break;
case NET_STATE_IDLE:
default:
{
/* check downchannel */

}
break;
}

/* set the multi_curl_handle */
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);

/* set a suitable timeout to play around with */
timeout.tv_sec = 1;
timeout.tv_usec = 0;

curl_multi_timeout(multi_handle, &curl_timeo);
if(curl_timeo >= 0) {
timeout.tv_sec = curl_timeo / 1000;
if(timeout.tv_sec > 1)
timeout.tv_sec = 1;
else
timeout.tv_usec = (curl_timeo % 1000) * 1000;
}

/* get file descriptors from the transfers */
mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);

if(mc != CURLM_OK) {
fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
break;
}
/* On success the value of maxfd is guaranteed to be >= -1. We call
select(maxfd + 1, ...); specially in case of (maxfd == -1) there are
no fds ready yet so we call select(0, ...) --or Sleep() on Windows--
to sleep 100ms, which is the minimum suggested value in the
curl_multi_fdset() doc. */
if(maxfd == -1) {
/* Portable sleep for platforms other than Windows. */
struct timeval wait = { 0, 100 * 1000 }; /* 100ms */
rc = select(0, NULL, NULL, NULL, &wait);
}
else {
/* Note that on some platforms 'timeout' may be modified by select().
If you need access to the original value save a copy beforehand. */
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch(rc) {
case -1:
/* select error */
printf("~~~~~this is error~~~\n");
break;
case 0:
default:
/* timeout or readable/writable sockets */
curl_multi_perform(multi_handle, &still_running);
break;
}

/* See how the transfers went */
while((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
if(msg->msg == CURLMSG_DONE) {
int idx, found = 0;

/* Find out which handle this message is about */
for(idx=0; idx<HANDLECOUNT; idx++) {
found = (msg->easy_handle == handles[idx]);
if(found)
break;
}

switch(idx) {
case DOWN_HANDLE:
printf("Downstream completed with status %d\n", msg->data.result);
curl_multi_add_handle(multi_handle, handles[DOWN_HANDLE]);
break;
case PING_HANDLE:
printf("ping completed with status %d\n", msg->data.result);
/* after send the ping, then remove the handle */
curl_multi_remove_handle(multi_handle , handles[PING_HANDLE]);
break;
case EVENT_HANDLE:
printf("event completed with status %d\n", msg->data.result);
curl_multi_remove_handle(multi_handle , handles[EVENT_HANDLE]);
free(headChunk.memory);
free(strJSONout);
strJSONout = NULL;
curl_formfree( postFirst);
break;
default:
break;
}
}
}

} while(1);

/* clean up */
curl_multi_cleanup(multi_handle);
/* Free the CURL handles */
for(i=0; i<HANDLECOUNT; i++)
curl_easy_cleanup(handles[i]);

/* free the custom headers */
curl_slist_free_all(downHead);
curl_slist_free_all(pingHead);
curl_slist_free_all(eventHead);

}
------------------------------------------------------------------------------------------

Thx

-------------------------------------------------------------------
List admin: https://cool.haxx.se/list/listinfo/curl-library
Etiquette: https://curl.haxx.se/mail/etiquette.html
Received on 2017-01-16