Skip to content

Instantly share code, notes, and snippets.

@akshayvernekar
Last active September 15, 2016 17:38
Show Gist options
  • Save akshayvernekar/faf0fccd0749e9cf1072503f0970ca6b to your computer and use it in GitHub Desktop.
Save akshayvernekar/faf0fccd0749e9cf1072503f0970ca6b to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <string.h>
#include <curl.h>
//#include <curl/curl.h>
//#include <utils/Log.h>
#define MULTI_PART_CONTENT_TYPE_AUDIO "application/octet-stream"
#define MULTI_PART_CONTENT_TYPE_JSON "application/json; charset=UTF-8"
#define DATA_SIZE 10
#define AUDIO_FILE_PATH "/media/usb/sample.wav"
#define DUMP_FILE_PATH "/media/usb/dump.txt"
#define AUTH_HEADER "Authorization: Bearer Atza|IwEBIFVtxdfnk8DwixLO1-xluOvXL9rqjUfhjT8YZT1fc7r0dmlk6tzh_UZi8aqBH55faqpUA9GCLkI93Hz4tiNUWtOwSwfkyhmgr5oVSUyZXMz1iK-zWlEEJyN7vJE7KRFzIHqeoubgGkksgBn6yg_QDRTM07OctS09jj3h8_YV1Xn3p-iGKYIgTXoOQrigrRTCJA5xVAhbaI-li0DXm7poDOnco3yawGJ5SVYzraCs1q-gXv5DgujgvfAH70xC5gRmq0IqXI4zKl5Qkf79LpFOM5JIKcQGm8pdCrqbhoQ7GvtXxjtEhTwuKLm-jRPy4DMjgdM8LqwajdMOxBz01xl56nXkx4tmT4wpRX8i7g57j-vO7hxZCnyeKWj-FbZP_Z2yoVqddAwpUmGNhFDGWoRnVOK7DWCL_tH9ihiQ5isdbFerr2rVh-R2EpOfJ3PJLaa7JSo7krLkvVjTz8GZBt_Oj017XvwcuTrj3pfwatjSday7pQMX1kxPm4J4QvkpOkMK4PLIV_tDnNn-WpUfLXKhiKbKKTJdS0BuBXSr525ikpTgLUWqjFvGX07g18oE-tMgDdY"
const char *metadata = "{\"context\":[{\"header\":{\"name\":\"PlaybackState\",\"namespace\":\"AudioPlayer\"},\"payload\":{\"offsetInMilliseconds\":0,\"playerActivity\":\"IDLE\",\"token\":\"\"}},{\"header\":{\"name\":\"SpeechState\",\"namespace\":\"SpeechSynthesizer\"},\"payload\":{\"offsetInMilliseconds\":0,\"playerActivity\":\"IDLE\",\"token\":\"\"}},{\"header\":{\"name\":\"AlertsState\",\"namespace\":\"Alerts\"},\"payload\":{\"activeAlerts\":[],\"allAlerts\":[]}},{\"header\":{\"name\":\"VolumeState\",\"namespace\":\"Speaker\"},\"payload\":{\"mute\":false,\"volume\":50}}],\"event\":{\"header\":{\"dialogRequestId\":\"12345678990\",\"messageId\":\"TAKE FROM UPNP\",\"name\":\"Recognize\",\"namespace\":\"SpeechRecognizer\"},\"payload\":{\"format\":\"AUDIO_L16_RATE_16000_CHANNELS_1\",\"profile\":\"CLOSE_TALK\"}}}";
int Curr_index ;
struct data {
char trace_ascii; /* 1 or 0 */
};
static
void dump(const char *text,
FILE *stream, unsigned char *ptr, size_t size,
char nohex)
{
size_t i;
size_t c;
unsigned int width=0x10;
if(nohex)
/* without the hex output, we can fit more on screen */
width = 0x40;
fprintf(stream, "%s, %10.10ld bytes (0x%8.8lx)\n",
text, (long)size, (long)size);
for(i=0; i<size; i+= width) {
fprintf(stream, "%4.4lx: ", (long)i);
if(!nohex) {
/* hex not disabled, show it */
for(c = 0; c < width; c++)
if(i+c < size)
fprintf(stream, "%02x ", ptr[i+c]);
else
fputs(" ", stream);
}
for(c = 0; (c < width) && (i+c < size); c++) {
/* check for 0D0A; if found, skip past and start a new line of output */
if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
i+=(c+2-width);
break;
}
fprintf(stream, "%c",
(ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
/* check again for 0D0A, to avoid an extra \n if it's at width */
if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
i+=(c+3-width);
break;
}
}
fputc('\n', stream); /* newline */
}
fflush(stream);
}
static
int my_trace(CURL *handle, curl_infotype type,
char *data, size_t size,
void *userp)
{
//struct data *config = (struct data *)userp;
FILE *outf = (FILE *)userp;
const char *text;
(void)handle; /* prevent compiler warning */
switch (type) {
case CURLINFO_TEXT:
fprintf(stderr, "== Info: %s", data);
default: /* in case a new one is introduced to shock us */
return 0;
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
case CURLINFO_DATA_OUT:
text = "=> Send data";
break;
case CURLINFO_SSL_DATA_OUT:
text = "=> Send SSL data";
break;
case CURLINFO_HEADER_IN:
text = "<= Recv header";
break;
case CURLINFO_DATA_IN:
text = "<= Recv data";
break;
case CURLINFO_SSL_DATA_IN:
text = "<= Recv SSL data";
break;
}
if(outf == NULL)
{
//ALOGE("a<-- cannot open file");
return false;
}
dump(text, outf, (unsigned char *)data, size, 1);
return 0;
}
static int getTransferStatus(CURLM *multiHandleInstance,CURL *currentHandle)
{
//check the status of transfer CURLcode return_code=0;
int msgs_left=0;
CURLMsg *msg=NULL;
CURL *eh=NULL;
CURLcode return_code;
int http_status_code = 0;
while ((msg = curl_multi_info_read(multiHandleInstance, &msgs_left)))
{
if (msg->msg == CURLMSG_DONE) {
eh = msg->easy_handle;
if(currentHandle == eh)
{
return_code = msg->data.result;
if((return_code!=CURLE_OK) &&(return_code != CURLE_RECV_ERROR))
{
fprintf(stderr, "CURL error code: %d\n", msg->data.result);
continue;
}
// Get HTTP status code
http_status_code=0;
curl_easy_getinfo(eh, CURLINFO_RESPONSE_CODE, &http_status_code);
}
}
}
return http_status_code;
}
static size_t processResponse(void *ptr, size_t size, size_t nmemb, void *instance)
{
//write callback
//ALOGE("a<-- we got response download size =%d",size * nmemb);
return size * nmemb;
}
static size_t datareader(void *ptr, size_t size, size_t nmemb, void* userp)
{
FILE *stream = (FILE *)userp;
//upload the file
size_t retcode = fread(ptr, size, nmemb, stream);
return retcode;
}
int main(void)
{
const char *postUrl = "https://54.239.23.243/v20160207/events";
CURLM *multi_handle = curl_multi_init();
int still_running = 0;
Curr_index = 0;
/*I want to upload the data using chunked encoding,
which means I dont know the total content size */
struct curl_slist *header = NULL;
header = curl_slist_append(header, "Host: access-alexa-na.amazon.com");
header = curl_slist_append(header, "Content-Type: multipart/form-data");
header = curl_slist_append(header, "Transfer-Encoding: chunked");
header = curl_slist_append(header, AUTH_HEADER);
struct curl_httppost *formpost = NULL;
struct curl_httppost *lastptr = NULL;
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "metadata",
CURLFORM_COPYCONTENTS, metadata,
CURLFORM_CONTENTTYPE, MULTI_PART_CONTENT_TYPE_JSON,
CURLFORM_END);
/*In below code I am commenting out the CONTENTSLENGTH
as i dont know the total size of the buffer,
the behaviour is same when when CONTENTSLENGTH
is commented or set to a false value.The transfer never gets completed. */
/*Curl documentation for CURLFORM_STREAM( [https://curl.haxx.se/libcurl/c/curl_formadd.html] )
tells developers its mandatory to set the CURLFORM_CONTENTSLENGTH,
In cases in "Chunked" transfer encoding the CONTENTSLENGTH is not known*/
FILE *sampleAudio = fopen(AUDIO_FILE_PATH,"rb");
if(sampleAudio == NULL)
{
//ALOGE("a<--couldnt open audio file ");
return 0;
}
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "audio",
CURLFORM_CONTENTTYPE, MULTI_PART_CONTENT_TYPE_AUDIO,
CURLFORM_STREAM, sampleAudio,
//CURLFORM_CONTENTSLENGTH, DATA_SIZE,
CURLFORM_END);
CURL *eventHttp_handle;
CURLcode res;
// init the curl session
eventHttp_handle = curl_easy_init();
if (eventHttp_handle)
{
struct data config;
curl_easy_setopt(eventHttp_handle, CURLOPT_URL, postUrl);
curl_easy_setopt(eventHttp_handle, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(eventHttp_handle, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(eventHttp_handle, CURLOPT_HTTP_VERSION,
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
/* disable progress meter, set to 0L to enable and disable debug output */
curl_easy_setopt(eventHttp_handle, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(eventHttp_handle, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(eventHttp_handle, CURLOPT_DEBUGFUNCTION, my_trace);
config.trace_ascii = 1; /* enable ascii tracing */
FILE *dumpFile = fopen(DUMP_FILE_PATH,"w");
curl_easy_setopt(eventHttp_handle, CURLOPT_DEBUGDATA, dumpFile);
//write callback function
curl_easy_setopt(eventHttp_handle, CURLOPT_WRITEFUNCTION, processResponse);
curl_easy_setopt(eventHttp_handle, CURLOPT_WRITEDATA, NULL);
//read callback function for sending audio
curl_easy_setopt(eventHttp_handle, CURLOPT_READFUNCTION, datareader);
curl_easy_setopt(eventHttp_handle, CURLOPT_READDATA,sampleAudio);
curl_easy_setopt(eventHttp_handle, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(eventHttp_handle, CURLOPT_HTTPHEADER, header);
//adding easy handle to Multihandle
curl_multi_add_handle(multi_handle, eventHttp_handle);
do {
CURLMcode mc;
int numfds;
/* when CURLFORM_CONTENTSLENGTH is set to false value
the "still_running" (active handles) never returns to 0*/
mc = curl_multi_perform(multi_handle, &still_running);
if(mc == CURLM_OK ) {
/* wait for activity, timeout or "nothing" */
mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
}
if(mc != CURLM_OK) {
fprintf(stderr, "curl_multi failed, code %d.n", mc);
break;
}
/* 'numfds' being zero means either a timeout or no file descriptors to
wait for. Try timeout on first occurrence, then assume no file
descriptors and no file descriptors to wait for means wait for 100
milliseconds. */
if(!numfds)
{
struct timeval wait = { 0, 100 * 1000 }; // 100ms
select(0, NULL, NULL, NULL, &wait);
}
} while(still_running);
if (header)
curl_slist_free_all(header);
if (formpost)
{
curl_formfree(formpost);
formpost = NULL;
}
fclose(dumpFile);
fclose(sampleAudio);
int responseCode = getTransferStatus(multi_handle,eventHttp_handle);
if(responseCode == 200)//200 OK!
{
// handle response body
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment